Wykluczyć podpakiety z automatycznego okablowania Spring?

83

Czy istnieje prosty sposób na wyłączenie pakietu / pakietu podrzędnego z automatycznego okablowania w Spring 3.1?

Np. Jeśli chciałbym dołączyć skan komponentu do pakietu podstawowego, com.exampleczy istnieje prosty sposób na wykluczenie com.example.ignore?

(Dlaczego? Chciałbym wykluczyć niektóre komponenty z moich testów integracji)

HolySamosa
źródło

Odpowiedzi:

85

Nie jestem pewien, czy możesz jawnie wykluczyć pakiety za pomocą <exclude-filter>, ale założę się, że użycie filtra regex skutecznie by Cię tam dostało:

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

Aby była oparta na adnotacjach, należy dodać adnotację do każdej klasy, którą chcesz wykluczyć z testów integracji, za pomocą czegoś takiego jak @ com.example.annotation.ExcludedFromITests. Wtedy skanowanie komponentów wyglądałoby następująco:

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

Jest to wyraźniejsze, ponieważ teraz udokumentowałeś w samym kodzie źródłowym, że klasa nie jest przeznaczona do włączenia do kontekstu aplikacji na potrzeby testów integracyjnych.

Jonathan W.
źródło
Korzystanie z filtru wykluczającego działa, ale nie musiałem uciekać przed „.”
Amin
2
@Amin To prawdopodobnie dlatego, że „.” uwzględnia wszystkie znaki, w tym dosłowne „.”
aksh1618
54

Używam @ComponentScanw następujący sposób dla tego samego przypadku użycia. To jest to samo, co odpowiedź XML BenSchro10, ale używa adnotacji. Oba używają filtru ztype=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
źródło
Może to czysta nostalgia, ale nadal wolę XML
Kirby,
10
to może być ja, ale ze Spring 4.2 muszę użyć FilterType.REGEXtego podejścia
ThanksForAllTheFish
To było to, czego chciałem, ale też musiałem to wykorzystać FilterType.REGEX. Może odpowiedź mogłaby zostać zaktualizowana, aby to odzwierciedlić?
Adam
1
Zapraszam do udzielenia nowej odpowiedzi
Kirby
38

W przypadku wiosny 4 używam następującego
(publikuję, ponieważ pytanie ma 4 lata i więcej osób korzysta z wiosny 4 niż wiosny 3.1):

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

Wygląda na to, że zrobiłeś to za pomocą XML, ale jeśli pracujesz z nowymi najlepszymi praktykami Spring, twoja konfiguracja byłaby w Javie i możesz je wykluczyć w następujący sposób:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "net.example.tool",
  excludeFilters = {@ComponentScan.Filter(
    type = FilterType.ASSIGNABLE_TYPE,
    value = {JPAConfiguration.class, SecurityConfig.class})
  })
Arsalan Khalid
źródło
9
@JonathanW Niemniej jednak, naprawdę przydatna odpowiedź dla osób przychodzących na tę stronę z wyszukiwarki Google
Stewart
12

Działa to w wersji Spring 3.0.5. Więc myślę, że zadziała w 3.1

<context:component-scan base-package="com.example">  
    <context:exclude-filter type="aspectj" expression="com.example.dontscanme.*" />  
</context:component-scan> 
BenSchro10
źródło
1
Pamiętaj, że po cichu ignoruje wykluczenie w przypadku, gdy aspektj nie jest obecny w ścieżce klas.
Vadzim
7

Myślę, że powinieneś refaktoryzować swoje pakiety w wygodniejszej hierarchii, aby nie znajdowały się w pakiecie podstawowym.

Ale jeśli nie możesz tego zrobić, spróbuj:

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

Tutaj możesz znaleźć więcej przykładów: Korzystanie z filtrów w celu dostosowania skanowania

richarbernal
źródło
Dzięki, w zasadzie zgadzam się z ideą refaktoryzacji - to była moja pierwsza myśl. Niestety, nie jest to świetna opcja w mojej konkretnej sytuacji.
HolySamosa
Dobry projekt opakowania może uniknąć takich sytuacji, ale jeśli nie ... nie możesz hahaha, :)
richarbernal
4

Jedna rzecz, która wydaje się działać dla mnie, to:

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

Lub w XML:

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

To zastępuje domyślną resourcePattern, która jest "**/*.class".

Wydaje się, że jest to najbardziej bezpieczny sposób na dołączenie TYLKO twojego pakietu podstawowego, ponieważ ten resourcePattern byłby zawsze taki sam i względny w stosunku do twojego pakietu podstawowego.

leeor
źródło
2

Możesz również użyć @SpringBootApplication , które zgodnie z dokumentacją Springa ma taką samą funkcjonalność jak trzy następujące adnotacje: @Configuration , @EnableAutoConfiguration @ComponentScan w jednej adnotacji.

@SpringBootApplication(exclude= {Foo.class})
public class MySpringConfiguration {}
dorony
źródło
Według Javadoc, excludema wykluczyć określone klasy autokonfiguracji , a nie wszystkie klasy ze skanowania komponentów. Jeśli spróbujesz, pojawi się błąd „ Nie można wykluczyć następujących klas, ponieważ nie są one klasami automatycznej konfiguracji ”.
Abhijit Sarkar
1

Możesz również dołączyć konkretny pakiet i wykluczyć je, na przykład:

Uwzględnij i wyklucz (oba)

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

PO PROSTU wyklucz

@SpringBootApplication(exclude= {com.package1.class})
public class MySpringConfiguration {}
Rishabh Agarwal
źródło
Według Javadoc, excludema wykluczyć określone klasy autokonfiguracji , a nie wszystkie klasy ze skanowania komponentów. Jeśli spróbujesz, pojawi się błąd „ Nie można wykluczyć następujących klas, ponieważ nie są one klasami automatycznej konfiguracji ”.
Abhijit Sarkar