2014-08-28 9 views
5

Ich habe eine Klasse, die ich während des Scannens von Komponenten ausschließen möchte. Ich verwende den folgenden Code, das zu tun, aber das scheint nicht zu funktionieren, obwohl alles richtigComponentScan excludeFilters funktioniert im Frühjahr 4.0.6.RELEASE

@ComponentScan(basePackages = { "common", "adapter", "admin"}, excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = ServiceImpl.class) }) 
zu sein scheint

Eigentlich will ich „ServiceImpl“ Klasse haben, die „Service“ Schnittstelle implementiert, wird in verwendet wird, meine rest api-logik und während ich den integrationstest einer api mache, möchte ich diese implementation ausschließen und die gespottete implementation laden. Aber das scheint nicht so auch geschehen, nachdem der oben mit erhalte ich die folgenden Fehler

No qualifying bean of type [admin.Service] is defined: expected single matching bean but found 2: ServiceMockImpl,ServiceImpl 

ich zu sehr auf diese Zeit damit verbracht, aber nichts funktioniert.

Jede Hilfe wird geschätzt.

Antwort

21

Nach viel Arbeit und Forschung bemerkte ich, dass das Verhalten von Spring in Bezug auf das Scannen von Komponenten wenig merkwürdig ist.

Artefakte waren wie folgt aus:

„ServiceImpl“ Klasse die wirkliche Implementierung ist die „Service“ Schnittstelle implementiert. "ServiceMockImpl" ist die gespottete Implantationsklasse, die die "Service" -Schnittstelle implementiert.

Ich wollte die Komponente scannen, so dass es nur die "ServiceMockImpl" aber nicht "ServiceImpl" lädt.

Ich musste den "@ ComponentScan.Filter (type = FilterType.ASSIGNABLE_TYPE, value = ServiceImpl.class)" im "@ComponentScan" der Testkonfigurationsklasse hinzufügen, um diese bestimmte Klasse vom Komponentenscan auszuschließen. Aber beide Klassen wurden geladen, auch nachdem die obigen Änderungen durchgeführt wurden und Tests fehlgeschlagen waren.

Nach viel Arbeit und Forschung fand ich, dass die „ServiceImpl“ wurde wegen der anderen Klasse immer geladen, das und hat „@ComponentScan“ für alle Pakete auf der in sie geladen zu werden. Also habe ich den Code hinzugefügt, um die "Application" -Klasse von der Komponentenprüfung wie folgt auszuschließen "@ ComponentScan.Filter (type = FilterType.ASSIGNABLE_TYPE, value = Application.class)".

Danach hat es wie erwartet funktioniert.

-Code wie unten

@ComponentScan(excludeFilters = { 
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = OAuthCacheServiceImpl.class), 
    @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = Application.class) }, basePackages = { 
    "common", "adapter", "admin"}) 

Ich habe, dass viele Fragen gesehen auf die Komponente Scannen sind offen für lange daher dachte ich, diese Details hinzufügen, wie es jemand in der Zukunft helfen können.

HTH ...

+0

Dank! es hilft! – zhuguowei

+2

Tolle Idee! Das ist was für mich auch: '@ComponentScan (basePackages = "org.package", excludeFilters = @filter (Klassen = {Controller.class, Configuration.class}))' Sieht aus wie wir ausdrücklich haben Frühling zu sagen, Konfigurationsklassen überspringen. – Yuriy

1

Zuerst Dank sehr viel über die Antworten von @Yuriy und @ ripudam, aber was macht mich verwirrt ist, wenn mein excludeFilters enthält Configuration.class Ich habe @Import verwenden, um die zu importierende Classe, die mit @ Configuration.I kommentiert, wenn ich excludeFilters = {@Filter (type = FilterType.ANNOTATION, Wert {EnableWebMvc.class, Controller.class}) verwende, funktioniert alles gut. Der ContextLoaderListener registriert den Controller nicht zuerst .

Zum Beispiel

//@Import(value = { SecurityConfig.class, MethodSecurityConfig.class, RedisCacheConfig.class, QuartzConfig.class }) 
@ComponentScan(basePackages = { "cn.myself" }, excludeFilters = { 
     @Filter(type = FilterType.ANNOTATION,value={EnableWebMvc.class,Controller.class}) }) 
public class RootConfig { 
} 
0

ich ein Problem hatte, als @Configuration, @EnableAutoConfiguration und @ComponentScan mit bei dem Versuch, bestimmte Konfigurationsklassen auszuschließen, ist das, was es nicht funktioniert!

Schließlich löste ich das Problem mit @SpringBootApplication, die nach Spring Dokumentation die gleiche Funktionalität wie die drei oben in einer Anmerkung tut.

Ein weiterer Tipp ist, zu versuchen zuerst Ihr Paket-Scan (ohne basePackages Filter) ohne Veredelung.

@SpringBootApplication(exclude= {Foo.class}) 
public class MySpringConfiguration {} 
Verwandte Themen