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.