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)

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.


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);
    }
}

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

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

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> 

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


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.


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

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.