2013-09-24 8 views
39

ich eine Komponente, die ich von einem @ComponentScan in einem bestimmten @Configuration ausschließen möchten:ausschließen @Component von @ComponentScan

@Component("foo") class Foo { 
... 
} 

Ansonsten scheint es mit einer anderen Klasse in meinem Projekt zu kollidieren. Ich verstehe die Kollision nicht vollständig, aber wenn ich die @Component Anmerkung auskommentiere, funktionieren die Dinge so, wie ich es möchte. Aber andere Projekte, die auf diese Bibliothek angewiesen sind, erwarten, dass diese Klasse von Spring verwaltet wird. Daher möchte ich sie nur in meinem Projekt überspringen.

Ich versuchte @ComponentScan.Filter mit:

@Configuration 
@EnableSpringConfigured 
@ComponentScan(basePackages = {"com.example"}, excludeFilters={ 
    @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)}) 
public class MySpringConfiguration {} 

aber es scheint nicht zu funktionieren. Wenn ich FilterType.ASSIGNABLE_TYPE Versuche Sie sich mit, erhalte ich einen seltsamen Fehler über nicht in der Lage etwas scheinbar zufällige Klasse zu laden:

Verursacht durch: java.io.FileNotFoundException: Classpath Ressource [junit/Rahmen/TestCase.class] kann nicht sein, geöffnet, weil es nicht

existiert

ich habe auch versucht type=FilterType.CUSTOM wie folgt verwendet:

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 {} 

Aber das scheint nicht die Komponente aus dem Scan ausschließen, wie ich will.

Wie schließe ich es aus?

+0

können Sie die Antwort annehmen, wenn eine für Sie arbeitete? –

Antwort

45

Die Konfiguration scheint in Ordnung, außer dass Sie excludeFilters statt excludes verwenden sollten:

@Configuration @EnableSpringConfigured 
@ComponentScan(basePackages = {"com.example"}, excludeFilters={ 
    @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=Foo.class)}) 
public class MySpringConfiguration {} 
+0

Entschuldigung, das war ein Fehler beim Ausschneiden und Einfügen. Ich verwende excludeFilters. Ich werde einen anderen Blick werfen, der Fehler, der mir das gibt, ist wirklich bizarr ... – ykaganovich

14

Ein weiterer Ansatz ist es, neue bedingte Anmerkungen zu verwenden. Seit Ebene Spring 4 können Sie @Conditional Anmerkung verwenden:

@Component("foo") 
@Conditional(FooCondition.class) 
class Foo { 
    ... 
} 

und bedingte Logik definieren für die Registrierung von Foo Komponente:

public class FooCondition implements Condition{ 
    @Override 
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { 
     // return [your conditional logic] 
    }  
} 

Bedingte Logik kann auf Kontext basieren, da haben Sie Zugriff auf Bohnenfabrik.Wenn zum Beispiel „Bar“ Komponente ist nicht als Bean registriert:

return !context.getBeanFactory().containsBean(Bar.class.getSimpleName()); 

mit Frühlings-Boot (sollte für jedes neues Frühlings-Projekt verwendet werden), können Sie diese bedingten Anmerkungen verwenden:

  • @ConditionalOnBean
  • @ConditionalOnClass
  • @ConditionalOnExpression
  • @ConditionalOnJava
  • @ConditionalOnMissingBean
  • @ConditionalOnMissingClass
  • @ConditionalOnNotWebApplication
  • @ConditionalOnProperty
  • @ConditionalOnResource
  • @ConditionalOnWebApplication

Sie können auf diese Weise Konditionsklasse Schaffung vermeiden. Weitere Informationen finden Sie in den Spring Boot-Dokumenten.

+0

+1 für die Bedingungen, das ist ein viel sauberer Weg für mich als die Verwendung von Filtern. Ich habe noch nie Filter erhalten, die so konsistent arbeiten wie das bedingte Laden von Beans. – wondergoat77

26

explizite Typen in Scan-Filter zu verwenden ist für mich hässlich. Ich glaube, eleganter Ansatz ist eigenen Marker Annotation zu erstellen:

public @interface IgnoreDuringScan { 
} 

Mark Komponente, die mit ihm ausgeschlossen werden sollen:

@Component("foo") 
@IgnoreDuringScan 
class Foo { 
    ... 
} 

Und nicht enthalten diese Anmerkung von Ihrer Komponente Scan:

@ComponentScan(excludeFilters = @Filter(IgnoreDuringScan.class)) 
public class MySpringConfiguration {} 
+3

Das ist eine clevere Idee für den universellen Ausschluss, wird aber nicht helfen, wenn Sie eine Komponente aus nur einer Teilmenge von Anwendungskontexten in einem Projekt ausschließen wollen. Wirklich, um es allgemein auszuschließen, könnte man einfach die '@ Komponente' entfernen, aber ich denke nicht, dass das die Frage ist – Kirby

3

Wenn Sie zwei oder mehr Kriterien definieren müssen, müssen Sie das Array verwenden.

Für Fälle in diesem Abschnitt des Codes ich alle Klassen in der org.xxx.yyy Paket und einer anderen spezifischen Klasse, ausschließen möchten MyClassToExclude

@ComponentScan(   
     excludeFilters = { 
       @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.xxx.yyy.*"), 
       @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = MyClassToExclude.class) }) 
1

Ich hatte ein Problem, wenn mit @Configuration, @EnableAutoConfiguration und @ComponentScan beim Versuch, bestimmte Konfigurationsklassen auszuschließen, ist die Sache, es hat nicht funktioniert!

Schließlich löste ich das Problem, indem @SpringBootApplication mit, die nach Frühling Dokumentation hat die gleiche Funktionalität wie die in einer Anmerkung drei oben.

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

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