Виключити підпакети з автопроводу 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.