Исключить подпакеты из Spring autowiring?

83

Есть ли простой способ исключить пакет / подпакет из автоматического подключения в Spring 3.1?

Например, если бы я хотел включить сканирование компонентов в базовый пакет, com.exampleесть ли простой способ исключитьcom.example.ignore ?

(Почему? Я хотел бы исключить некоторые компоненты из моих интеграционных тестов)

HolySamosa
источник

Ответы:

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
@ Амин Это, наверное, потому что "." учитывает любой символ, включая буквальный "."
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 Но, тем не менее, действительно полезный ответ для людей,
Стюарт
12

Это работает в Spring 3.0.5. Итак, я бы подумал, что это будет работать в 3.1

<context:component-scan base-package="com.example">  
    <context:exclude-filter type="aspectj" expression="com.example.dontscanme.*" />  
</context:component-scan> 
BenSchro10
источник
1
Помните, что он молча игнорирует исключения в случае, если аспектj отсутствует в пути к классам.
Вадим
7

Я думаю, вам следует реорганизовать свои пакеты в более удобную иерархию, чтобы они не входили в базовый пакет.

Но если вы не можете этого сделать, попробуйте:

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

Здесь вы можете найти больше примеров: Использование фильтров для настройки сканирования

Ричарбернал
источник
Спасибо, в принципе согласен с идеей рефакторинга - это была моя первая мысль. К сожалению, это не лучший вариант для моей конкретной ситуации.
HolySamosa
Хороший дизайн упаковки может избежать таких ситуаций, но если вы не можете ... вы не можете, хахаха, :)
Ричарбернал,
4

Мне кажется, что одна вещь работает для меня:

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

Или в XML:

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

Это отменяет значение по умолчанию , resourcePatternкоторое "**/*.class".

Это может показаться наиболее безопасным для типов способом включения ТОЛЬКО вашего базового пакета, поскольку этот resourcePattern всегда будет таким же и относительно вашего базового пакета.

leeor
источник
2

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

@SpringBootApplication(exclude= {Foo.class})
public class MySpringConfiguration {}
Дорони
источник
Согласно Javadoc, excludeнеобходимо исключить определенные классы автоконфигурации , а не все классы из сканирования компонентов. Если вы попробуете, вы получите сообщение об ошибке « Следующие классы не могут быть исключены, потому что они не являются классами автоконфигурации ».
Абхиджит Саркар
1

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

Включить и исключить (оба)

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

ТОЛЬКО исключить

@SpringBootApplication(exclude= {com.package1.class})
public class MySpringConfiguration {}
Ришаб Агарвал
источник
Согласно Javadoc, excludeнеобходимо исключить определенные классы автоконфигурации , а не все классы из сканирования компонентов. Если вы попробуете, вы получите сообщение об ошибке « Следующие классы не могут быть исключены, потому что они не являются классами автоконфигурации ».
Абхиджит Саркар