Mam składnik, który chcę @ComponentScan
w szczególności wykluczyć @Configuration
:
@Component("foo") class Foo {
...
}
W przeciwnym razie wydaje się kolidować z inną klasą w moim projekcie. Nie do końca rozumiem kolizję, ale jeśli skomentuję @Component
adnotację, wszystko działa tak, jak chcę. Ale inne projekty, które opierają się na tej bibliotece, oczekują, że ta klasa będzie zarządzana przez Spring, więc chcę ją pominąć tylko w moim projekcie.
Próbowałem użyć @ComponentScan.Filter
:
@Configuration
@EnableSpringConfigured
@ComponentScan(basePackages = {"com.example"}, excludeFilters={
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)})
public class MySpringConfiguration {}
ale wygląda na to, że nie działa. Jeśli spróbuję użyć FilterType.ASSIGNABLE_TYPE
, pojawia się dziwny błąd dotyczący niemożności załadowania pozornie przypadkowej klasy:
Przyczyna: java.io.FileNotFoundException: nie można otworzyć zasobu ścieżki klasy [junit / framework / TestCase.class], ponieważ nie istnieje
Próbowałem również użyć type=FilterType.CUSTOM
następujących:
class ExcludeFooFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) throws IOException {
return metadataReader.getClass() == Foo.class;
}
}
@Configuration @EnableSpringConfigured
@ComponentScan(basePackages = {"com.example"}, excludeFilters={
@ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)})
public class MySpringConfiguration {}
Ale to nie wydaje się wykluczać komponentu ze skanowania, tak jak chcę.
Jak to wykluczyć?
źródło
Używanie jawnych typów w filtrach skanowania jest dla mnie brzydkie. Uważam, że bardziej eleganckim podejściem jest utworzenie własnej adnotacji znacznika:
@Retention(RetentionPolicy.RUNTIME) public @interface IgnoreDuringScan { }
Zaznacz komponent, który powinien być z nim wykluczony:
@Component("foo") @IgnoreDuringScan class Foo { ... }
I wyklucz tę adnotację ze skanowania komponentu:
@ComponentScan(excludeFilters = @Filter(IgnoreDuringScan.class)) public class MySpringConfiguration {}
źródło
@Component
, ale nie sądzę, że o to chodziInnym podejściem jest użycie nowych adnotacji warunkowych. Od zwykłej Spring 4 możesz używać adnotacji @Conditional:
@Component("foo") @Conditional(FooCondition.class) class Foo { ... }
i zdefiniuj warunkową logikę rejestracji komponentu Foo:
public class FooCondition implements Condition{ @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // return [your conditional logic] } }
Logika warunkowa może być oparta na kontekście, ponieważ masz dostęp do fabryki fasoli. Na przykład, gdy komponent „Bar” nie jest zarejestrowany jako ziarno:
return !context.getBeanFactory().containsBean(Bar.class.getSimpleName());
Dzięki Spring Boot (powinien być używany dla KAŻDEGO nowego projektu Spring) możesz użyć następujących adnotacji warunkowych:
@ConditionalOnBean
@ConditionalOnClass
@ConditionalOnExpression
@ConditionalOnJava
@ConditionalOnMissingBean
@ConditionalOnMissingClass
@ConditionalOnNotWebApplication
@ConditionalOnProperty
@ConditionalOnResource
@ConditionalOnWebApplication
W ten sposób możesz uniknąć tworzenia klasy Warunków. Więcej szczegółów można znaleźć w dokumentacji Spring Boot.
źródło
Jeśli chcesz zdefiniować dwa lub więcej kryteriów excludeFilters , musisz użyć tablicy.
W przypadku instancji w tej sekcji kodu chcę wykluczyć wszystkie klasy z pakietu org.xxx.yyy i inną określoną klasę, MyClassToExclude
@ComponentScan( excludeFilters = { @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.xxx.yyy.*"), @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyClassToExclude.class) })
źródło
Miałem problem podczas używania @Configuration , @EnableAutoConfiguration i @ComponentScan podczas próby wykluczenia określonych klas konfiguracyjnych, chodzi o to, że nie działało!
Ostatecznie rozwiązałem problem za pomocą @SpringBootApplication , która zgodnie z dokumentacją Springa ma taką samą funkcjonalność jak trzy powyższe w jednej adnotacji.
Inną wskazówką jest, aby spróbować najpierw bez udoskonalania skanowania pakietów (bez filtra basePackages).
@SpringBootApplication(exclude= {Foo.class}) public class MySpringConfiguration {}
źródło
W przypadku wykluczenia komponentu testowego lub konfiguracji testowej, Spring Boot 1.4 wprowadził nowe adnotacje testowe
@TestComponent
i@TestConfiguration
.źródło
Musiałem wykluczyć inspekcję @Aspect @Component z kontekstu aplikacji, ale tylko dla kilku klas testowych. Skończyło się na użyciu @Profile („audit”) w klasie aspektu; w tym profil dla normalnych operacji, ale wykluczając go (nie umieszczaj go w @ActiveProfiles) w określonych klasach testowych.
źródło