Как предотвратить использование определенных пакетов 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).*"
которое является регулярным выражением