如何防止某些软件包与ArchUnit一起使用spring?

时间:2018-12-14 22:41:58

标签: java spring domain-driven-design hexagonal-architecture archunit

如果我想通过 ArchUnit 使某个Java程序包不受第三方依赖,我该怎么办?

更具体地说,我正在寻找将域模型保持在没有弹簧代码的六角形体系结构中的方法。我指定了一些规则,我认为应该防止该模型使用spring。但是,我可以使用@Component@Bean之类的spring注释,而不会引起冲突。

到目前为止,我尝试过的是

layeredArchitecture().
  layer("domain").definedBy(DOMAIN_LAYER).
  layer("application").definedBy(APPLICATION_LAYER).
  layer("primary-adapters").definedBy(PRIMARY_ADAPTERS).
  layer("secondary-adapters").definedBy(SECONDARY_ADAPTERS).
  layer("spring").definedBy("org.springframework..")
  whereLayer("spring").mayOnlyBeAccessedByLayers("primary-adapters", "secondary-adapters", "application").
  because("Domain should be kept spring-free").
  check(CLASSES);

以及

noClasses().that().resideInAPackage(DOMAIN_LAYER).
should().dependOnClassesThat().resideInAPackage("org.springframework..").
check(CLASSES);

noClasses().that().resideInAPackage(DOMAIN_LAYER).
should().accessClassesThat().resideInAPackage("org.springframework..").
check(CLASSES);

Here一个代码示例,尽管com.example.app.domain.Factory正在导入org.springframework...,但该代码示例可以很好地执行测试。

2 个答案:

答案 0 :(得分:0)

您可以使用DescribedPredicate:

void domainSpring() {
    DescribedPredicate<JavaAnnotation> springAnnotationPredicate = new DescribedPredicate<JavaAnnotation>("Spring filter") {
        @Override
        public boolean apply(JavaAnnotation input) {
            return input.getType().getPackageName().startsWith("org.springframework");
        }
    };
    classes().that().resideInAPackage(DOMAIN_LAYER).should()
            .notBeAnnotatedWith(springAnnotationPredicate).check(CLASSES);

}

答案 1 :(得分:0)

您也可以使用名称匹配。 因此您不必编写自定义 DescribedPredicate

 ApplicationCoreMustNotDependOnFrameworks = noClasses()
       .that().resideInAnyPackage(DOMAIN_LAYER)
       .should().dependOnClassesThat().haveNameMatching("org.springframework.")
       .orShould().dependOnClassesThat().haveNameMatching("javax.persistence.*")
       .because("Domain should be free from Frameworks");

就我而言,我想要该规则的例外。 即,我想接受事件包中的类,而不是完全排除 Spring (EventHanlder) 所以你可以用 "org.springframework" 替换 "org.springframework(?!.*event).*",这是一个正则表达式