导入类的方法提供了多维度的参数,用起来会十分便捷。例如想导入com.sample包下面的所有类,只需要这样:
public class ClassFileImporterTest { @Test public void testImportBootstarpClass() throws Exception { ImportOptions importOptions = new ImportOptions() // 不扫描jar包 .with(ImportOption.Predefined.DONT_INCLUDE_JARS) // 排除不扫描的包 .with(new DontIncludePackagesImportOption("com.sample..support")); ClassFileImporter classFileImporter = new ClassFileImporter(importOptions); long start = System.currentTimeMillis(); JavaClasses javaClasses = classFileImporter.importPackages("com.sample"); long end = System.currentTimeMillis(); System.out.println(String.format("Found %d classes,cost %d ms", javaClasses.size(), end - start)); } }得到的JavaClasses是JavaClass的集合,可以简单类比为反射中Class的集合,后面使用的代码规则和依赖规则判断都是强依赖于JavaClasses或者JavaClass。
内建规则定义类扫描和类导入完成之后,我们需要定检查规则,然后应用于所有导入的类,这样子就能完成对所有的类进行规则的过滤 - 或者说把规则应用于所有类并且进行断言。
规则定义依赖于ArchRuleDefinition类,创建出来的规则是ArchRule实例,规则实例的创建过程一般使用ArchRuleDefinition类的流式方法,这些流式方法定义上符合人类思考的思维逻辑,上手比较简单,举个例子:
ArchRule archRule = ArchRuleDefinition.noClasses() // 在service包下的所有类 .that().resideInAPackage("..service..") // 不能调用controller包下的任意类 .should().accessClassesThat().resideInAPackage("..controller..") // 断言描述 - 不满足规则的时候打印出来的原因 .because("不能在service包中调用controller中的类"); // 对所有的JavaClasses进行判断 archRule.check(classes);上面展示了自定义新的ArchRule的例子,中已经为我们内置了一些常用的ArchRule实现,它们位于GeneralCodingRules中:
NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS:不能调用System.out、System.err或者(Exception.)printStackTrace。
NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS:类不能直接抛出通用异常Throwable、Exception或者RuntimeException。
NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING:不能使用java.util.logging包路径下的日志组件。
更多内建的ArchRule或者通用的内置规则使用,可以参考官方例子。
基本使用例子基本使用例子,主要从一些常见的编码规范或者项目规范编写规则对项目所有类进行检查。
包依赖关系检查 ArchRule archRule = ArchRuleDefinition.noClasses() .that().resideInAPackage("..com.source..") .should().dependOnClassesThat().resideInAPackage("..com.target.."); ArchRule archRule = ArchRuleDefinition.classes() .that().resideInAPackage("..com.foo..") .should().onlyAccessClassesThat().resideInAnyPackage("..com.source..", "..com.foo.."); 类依赖关系检查 ArchRule archRule = ArchRuleDefinition.classes() .that().haveNameMatching(".*Bar") .should().onlyBeAccessed().byClassesThat().haveSimpleName("Bar"); 类包含于包的关系检查 ArchRule archRule = ArchRuleDefinition.classes() .that().haveSimpleNameStartingWith("Foo") .should().resideInAPackage("com.foo"); 继承关系检查 ArchRule archRule = ArchRuleDefinition.classes() .that().implement(Collection.class) .should().haveSimpleNameEndingWith("Connection");