Unterpakete von Spring Autowiring ausschließen?

81

Gibt es eine einfache Möglichkeit, ein Paket / Unterpaket in Spring 3.1 vom Autowiring auszuschließen?

Wenn ich beispielsweise einen Komponentenscan in ein Basispaket von aufnehmen möchte, com.examplegibt es eine einfache Möglichkeit, dies auszuschließen com.example.ignore?

(Warum? Ich möchte einige Komponenten von meinen Integrationstests ausschließen.)

HolySamosa
quelle

Antworten:

83

Ich bin nicht sicher, ob Sie Pakete explizit mit einem <Ausschluss-Filter> ausschließen können, aber ich wette, die Verwendung eines Regex-Filters würde Sie effektiv dorthin bringen:

 <context:component-scan base-package="com.example">
    <context:exclude-filter type="regex" expression="com\.example\.ignore\..*"/>
 </context:component-scan>

Um es annotationsbasiert zu machen, würden Sie jede Klasse, die Sie für Integrationstests ausgeschlossen haben möchten, mit @ com.example.annotation.ExcludedFromITests kommentieren. Dann würde der Komponentenscan folgendermaßen aussehen:

 <context:component-scan base-package="com.example">
    <context:exclude-filter type="annotation" expression="com.example.annotation.ExcludedFromITests"/>
 </context:component-scan>

Das ist klarer, da Sie jetzt im Quellcode selbst dokumentiert haben, dass die Klasse nicht für Integrationstests in einem Anwendungskontext enthalten sein soll.

Jonathan W.
quelle
Die Verwendung des Ausschlussfilters funktioniert, aber ich musste nicht "."
Amin
1
@Amin Das liegt wahrscheinlich daran, dass "." berücksichtigt jedes Zeichen einschließlich des wörtlichen "."
Aksh1618
54

Ich verwende @ComponentScanFolgendes für denselben Anwendungsfall. Dies entspricht der XML-Antwort von BenSchro10 , verwendet jedoch Anmerkungen. Beide verwenden einen Filter mittype=AspectJ

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@EnableAutoConfiguration
@ComponentScan(basePackages = { "com.example" },
    excludeFilters = @ComponentScan.Filter(type = FilterType.ASPECTJ, pattern = "com.example.ignore.*"))
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Kirby
quelle
Vielleicht ist es reine Nostalgie, aber ich bevorzuge eigentlich immer noch XML
Kirby
10
Ich mag es sein, aber mit Spring 4.2 muss ich FilterType.REGEXfür diesen Ansatz verwenden
ThanksForAllTheFish
Das wollte ich, aber ich musste es auch benutzen FilterType.REGEX. Vielleicht könnte die Antwort aktualisiert werden, um dies widerzuspiegeln?
Adam
1
Fühlen Sie sich frei, eine neue Antwort zu geben
Kirby
36

Für Spring 4 verwende ich Folgendes
(ich poste es, da die Frage 4 Jahre alt ist und mehr Leute Spring 4 als Spring 3.1 verwenden):

@Configuration
@ComponentScan(basePackages = "com.example", 
  excludeFilters = @Filter(type=FilterType.REGEX,pattern="com\\.example\\.ignore\\..*")) 
public class RootConfig {
    // ...
}
Witold Kaczurba
quelle
13

Es scheint, dass Sie dies über XML getan haben, aber wenn Sie in der neuen Best Practice von Spring arbeiten würden, wäre Ihre Konfiguration in Java, und Sie könnten sie wie folgt ausschließen:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "net.example.tool",
  excludeFilters = {@ComponentScan.Filter(
    type = FilterType.ASSIGNABLE_TYPE,
    value = {JPAConfiguration.class, SecurityConfig.class})
  })
Arsalan Khalid
quelle
Obwohl Sie feststellen, dass diese Frage älter als 4 Jahre ist und speziell für Spring 3.1 gestellt wurde, oder?
Jonathan W
8
@ JonathanW Aber dennoch eine wirklich nützliche Antwort für Leute, die von einer Google-Suche auf diese Seite kommen
Stewart
12

Dies funktioniert in Spring 3.0.5. Ich würde also denken, dass es in 3.1 funktionieren würde

<context:component-scan base-package="com.example">  
    <context:exclude-filter type="aspectj" expression="com.example.dontscanme.*" />  
</context:component-scan> 
BenSchro10
quelle
1
Beachten Sie, dass der Ausschluss stillschweigend ignoriert wird, falls Aspektj im Klassenpfad nicht vorhanden ist.
Vadzim
7

Ich denke, Sie sollten Ihre Pakete in einer bequemeren Hierarchie umgestalten, damit sie nicht im Basispaket enthalten sind.

Aber wenn Sie dies nicht können, versuchen Sie:

<context:component-scan base-package="com.example">
    ...
    <context:exclude-filter type="regex" expression="com\.example\.ignore.*"/>
</context:component-scan>

Hier finden Sie weitere Beispiele: Verwenden von Filtern zum Anpassen des Scannens

richarbernal
quelle
Vielen Dank, im Prinzip stimme ich der Idee des Refactorings zu - es war mein erster Gedanke. Leider ist es für meine spezielle Situation keine wirklich gute Option.
HolySamosa
Gutes Verpackungsdesign kann diese Situationen vermeiden, aber wenn Sie nicht ... können Sie nicht hahaha, :)
richarbernal
4

Eine Sache, die für mich zu funktionieren scheint, ist folgende:

@ComponentScan(basePackageClasses = {SomeTypeInYourPackage.class}, resourcePattern = "*.class")

Oder in XML:

<context:component-scan base-package="com.example" resource-pattern="*.class"/>

Dies überschreibt den Standard , resourcePatterndas ist "**/*.class".

Dies scheint die typsicherste Möglichkeit zu sein, NUR Ihr Basispaket einzuschließen, da dieses Ressourcenmuster immer dasselbe und relativ zu Ihrem Basispaket ist.

Leeor
quelle
3

Sie können auch @SpringBootApplication verwenden , das laut Spring-Dokumentation dieselbe Funktionalität wie die folgenden drei Anmerkungen bietet : @Configuration , @EnableAutoConfiguration @ComponentScan in einer Anmerkung.

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

Sie können auch ein bestimmtes Paket einschließen und ausschließen wie:

Einschließen und Ausschließen (beide)

 @SpringBootApplication
        (
                scanBasePackages = {
                        "com.package1",
                        "com.package2"
                },
                exclude = {org.springframework.boot.sample.class}
        )

NUR ausschließen

@SpringBootApplication(exclude= {com.package1.class})
public class MySpringConfiguration {}
Rishabh Agarwal
quelle