Виключити підпакети з автопроводу Spring?


83

Чи існує простий спосіб виключити пакет / підпакет з автоматичного підключення навесні 3.1?

Наприклад, якщо я хотів включити сканування компонентів з базовим пакетом, com.exampleчи існує простий спосіб виключити com.example.ignore?

(Чому? Я хотів би виключити деякі компоненти зі своїх інтеграційних тестів)

Відповіді:


85

Я не впевнений, що ви можете явно виключити пакети за допомогою <exclude-filter>, але я впевнений, що використання фільтра регулярних виразів ефективно допоможе вам потрапити туди:

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

Щоб зробити це на основі анотацій, ви коментуєте кожен клас, який ви хотіли виключити для тестів інтеграції, чимось на кшталт @ com.example.annotation.ExcludedFromITests. Тоді сканування компонентів буде виглядати так:

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

Це зрозуміліше, оскільки тепер ви зафіксували в самому вихідному коді, що клас не призначений для включення в контекст програми для тестів інтеграції.


Використання фільтра виключення працює, але мені не довелося втікати "."
Амін

2
@Amin Це, мабуть, тому, що "." враховує будь-який символ, включаючи буквальний "."
aksh1618

54

Я використовую @ComponentScanнаступне для того самого випадку використання. Це те саме, що і відповідь XML на BenSchro10, але тут використовуються анотації. Обидва використовують фільтр зtype=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);
    }
}

Можливо, це суто ностальгія, але я насправді віддаю перевагу XML все-таки
Кірбі

10
це може бути я, але з Spring 4.2 я повинен використовувати FilterType.REGEXдля цього підхід
ThanksForAllTheFish

Це те, що я хотів, але мені також довелося скористатися FilterType.REGEX. Можливо, відповідь можна оновити, щоб відобразити це?
Адам

1
Не соромтеся давати нову відповідь
Кірбі

38

Для Spring 4 я використовую наступне
(я публікую його, оскільки запиту 4 роки, і більше людей використовують Spring 4, ніж Spring 3.1):

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

13

Здається, ви зробили це за допомогою XML, але якби ви працювали в новій найкращій практиці Spring, ваша конфігурація була б на Java, і ви могли б виключити їх так:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "net.example.tool",
  excludeFilters = {@ComponentScan.Filter(
    type = FilterType.ASSIGNABLE_TYPE,
    value = {JPAConfiguration.class, SecurityConfig.class})
  })

9
@JonathanW Але тим не менш, дійсно корисна відповідь для людей, які заходять на цю сторінку з пошуку в Google
Стюарт

12

Це працює навесні 3.0.5. Отже, я думаю, це спрацює в 3.1

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

1
Пам'ятайте, що воно мовчки ігнорує виключення, якщо аспектj відсутній у шляху до класу.
Вадзім

7

Я думаю, вам слід переробляти свої пакети в більш зручній ієрархії, щоб вони виходили за межі базового пакета.

Але якщо ви не можете цього зробити, спробуйте:

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

Тут ви можете знайти більше прикладів: Використання фільтрів для налаштування сканування


Дякую, в принципі я погоджуюся з ідеєю рефакторингу - це була моя перша думка. На жаль, це не дуже хороший варіант для моєї конкретної ситуації.
HolySamosa

Хороший дизайн упаковки дозволяє уникнути цієї ситуації, але якщо ви не можете ... ви не можете ха-ха-ха, :)
richarbernal

4

Одне, що мені здається, працює:

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

Або в XML:

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

Це скасовує значення за замовчуванням , resourcePatternяке "**/*.class".

Це здається найбезпечнішим способом включити ТІЛЬКИ ваш базовий пакет, оскільки цей ресурсPattern завжди буде однаковим і відносно вашого базового пакета.


2

Ви також можете використовувати @SpringBootApplication , який згідно з документацією Spring виконує ту ж функціональність, що й наступні три анотації: @Configuration , @EnableAutoConfiguration @ComponentScan в одній анотації.

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

Згідно з Javadoc, excludeце Виключення певних класів автоконфігурації , а не всіх класів із сканування компонентів. Якщо ви спробуєте, ви отримаєте повідомлення про помилку " Наступні класи не можна виключити, оскільки вони не є класами автоконфігурації ".
Abhijit Sarkar

1

Ви також можете включити певний пакет і виключити їх, наприклад:

Включити та виключити (обидва)

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

ПРОСТО виключити

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

Згідно з Javadoc, excludeце Виключення певних класів автоконфігурації , а не всіх класів із сканування компонентів. Якщо ви спробуєте, ви отримаєте повідомлення про помилку " Наступні класи не можна виключити, оскільки вони не є класами автоматичної конфігурації ".
Abhijit Sarkar
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.