Как предотвратить использование определенных пакетов Spring с ArchUnit?

Если бы я хотел сохранить определенный пакет Java свободным от сторонних зависимостей с помощью ArchUnit, как бы я это сделал?

Точнее говоря, я пытаюсь сохранить мою модель предметной области в гексагональной архитектуре свободной от Spring-кода. Я указал некоторые правила, которые, по моему мнению, должны помешать модели использовать пружину. Тем не менее, я могу использовать весенние аннотации, такие как @Component а также @Bean без причинения нарушения.

То, что я пробовал до сих пор,

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);

Вот пример кода, который выполняет тесты просто отлично, хотя com.example.app.domain.Factory импортирует org.springframework...,

2 ответа

Решение

Вы можете использовать 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);

}

Вы также можете пойти с сопоставлением имен. Так что вам не нужно писать обычай 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).*" которое является регулярным выражением

Другие вопросы по тегам