/*
* @since 3.1
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
/**
* Alias for {@link #basePackages}.
* <p>Allows for more concise annotation declarations if no other attributes
* are needed — for example, {@code @ComponentScan("org.my.pkg")}
* instead of {@code @ComponentScan(basePackages = "org.my.pkg")}.
*/
@AliasFor("basePackages")
String[] value() default {};
/**
* Base packages to scan for annotated components.
* <p>{@link #value} is an alias for (and mutually exclusive with) this
* attribute.
* <p>Use {@link #basePackageClasses} for a type-safe alternative to
* String-based package names.
*/
@AliasFor("value")
String[] basePackages() default {};
/**
* Indicates whether automatic detection of classes annotated with {@code @Component}
* {@code @Repository}, {@code @Service}, or {@code @Controller} should be enabled.
*/
boolean useDefaultFilters() default true;
/**
* Specifies which types are eligible for component scanning.
* <p>Further narrows the set of candidate components from everything in {@link #basePackages}
* to everything in the base packages that matches the given filter or filters.
* <p>Note that these filters will be applied in addition to the default filters, if specified.
* Any type under the specified base packages which matches a given filter will be included,
* even if it does not match the default filters (i.e. is not annotated with {@code @Component}).
* @see #resourcePattern()
* @see #useDefaultFilters()
*/
Filter[] includeFilters() default {};
/**
* Specifies which types are not eligible for component scanning.
* @see #resourcePattern
*/
Filter[] excludeFilters() default {};
/**
* Declares the type filter to be used as an {@linkplain ComponentScan#includeFilters
* include filter} or {@linkplain ComponentScan#excludeFilters exclude filter}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({})
@interface Filter {
/**
* The type of filter to use.
* <p>Default is {@link FilterType#ANNOTATION}.
* @see #classes
* @see #pattern
*/
FilterType type() default FilterType.ANNOTATION;
/**
* Alias for {@link #classes}.
* @see #classes
*/
@AliasFor("classes")
Class<?>[] value() default {};
/**
* The class or classes to use as the filter.
* <p>The following table explains how the classes will be interpreted
* based on the configured value of the {@link #type} attribute.
* <table border="1">
* <tr><th>{@code FilterType}</th><th>Class Interpreted As</th></tr>
* <tr><td>{@link FilterType#ANNOTATION ANNOTATION}</td>
* <td>the annotation itself</td></tr>
* <tr><td>{@link FilterType#ASSIGNABLE_TYPE ASSIGNABLE_TYPE}</td>
* <td>the type that detected components should be assignable to</td></tr>
* <tr><td>{@link FilterType#CUSTOM CUSTOM}</td>
* <td>an implementation of {@link TypeFilter}</td></tr>
* </table>
* <p>When multiple classes are specified, <em>OR</em> logic is applied
* — for example, "include types annotated with {@code @Foo} OR {@code @Bar}".
* <p>Custom {@link TypeFilter TypeFilters} may optionally implement any of the
* following {@link org.springframework.beans.factory.Aware Aware} interfaces, and
* their respective methods will be called prior to {@link TypeFilter#match match}:
* <ul>
* <li>{@link org.springframework.context.EnvironmentAware EnvironmentAware}</li>
* <li>{@link org.springframework.beans.factory.BeanFactoryAware BeanFactoryAware}
* <li>{@link org.springframework.beans.factory.BeanClassLoaderAware BeanClassLoaderAware}
* <li>{@link org.springframework.context.ResourceLoaderAware ResourceLoaderAware}
* </ul>
* <p>Specifying zero classes is permitted but will have no effect on component
* scanning.
* @since 4.2
* @see #value
* @see #type
*/
@AliasFor("value")
Class<?>[] classes() default {};
}
}
解讀@ComponentScan
@ComponentScan表示給帶有@Configuration的類配置一個組件掃描指令。
-
支持與Spring XML’s context:component-scan element 並行使用。
-
可以使用basePackageClasses, basePackages或者value屬性來指定已經定義的包目錄,
從而納入到掃描範圍內。
-
如果指定的包並不是一個正確的已定義的包,那麼將從
使用@ComponentScan註解的類所在包
開始掃描。 -
但如果沒有爲value或者basePackages配置值,那麼將從
使用@ComponentScan註解的類所在包及其子包
開始掃描。【這也就是爲什麼 @SpringBootApplication 內部的 @ComponentScan 沒有指定具體的
包,也能夠從啓動類所在包及其子包掃描到組件的原因】
-
特別的,由 @ComponentScan 上的 @Repeatable(ComponentScans.class) 我們可以進
一步得知 @ComponentScan 是可以重複使用的。
這就與在xml中,多次使用 context:component-scan 的效果相同。
-
需要注意的是,在 context:component-scan element 有 annotation-config 屬性,
但 annotation-config 在 @ComponentScan 中是不存在的。
這是因爲在大多數使用 @ComponentScan的場景下,我們總是假定使用默認annotation
config處理。
此外,當我們使用AnnotationConfigApplicationContext的時候,annotation config
processors 總是會進行註冊。
這也就意味着任何嘗試在 @ComponentScan 上禁用它們的操作將會被忽略。
-
如果單獨使用 @ComponentScan,即便配置上basePackages值,也不會對指定的包進行掃描,需要和@Configuration進行組合使用。
-
僅僅將一個類配上@Component是不會自動註冊到容器裏的,還得需要@ComponentScan。
-
@Configuration
new AnnotationConfigApplicationContext(ThirdConfig.class) /** * 創建一個AnnotationConfigApplicationContext對象,從給定的component classes得到bean的定義並且會自動刷新上下文 * <p/> * Create a new AnnotationConfigApplicationContext, deriving bean definitions * from the given component classes and automatically refreshing the context. * <p/> * @param componentClasses one or more component classes - for example, @Configuration classes */ public AnnotationConfigApplicationContext(Class<?>... componentClasses) { this(); // Register one or more component classes to be processed. register(componentClasses); refresh(); }
解讀FilterType
/**
* Enumeration of the type filters that may be used in conjunction with
* {@link ComponentScan @ComponentScan}.
*
* @since 2.5
* @see ComponentScan
* @see ComponentScan#includeFilters()
* @see ComponentScan#excludeFilters()
* @see org.springframework.core.type.filter.TypeFilter
*/
public enum FilterType {
/**
* Filter candidates marked with a given annotation.
* @see org.springframework.core.type.filter.AnnotationTypeFilter
*/
ANNOTATION,
/**
* Filter candidates assignable to a given type.
* @see org.springframework.core.type.filter.AssignableTypeFilter
*/
ASSIGNABLE_TYPE,
/**
* Filter candidates matching a given AspectJ type pattern expression.
* @see org.springframework.core.type.filter.AspectJTypeFilter
*/
ASPECTJ,
/**
* Filter candidates matching a given regex pattern.
* @see org.springframework.core.type.filter.RegexPatternTypeFilter
*/
REGEX,
/** Filter candidates using a given custom
* {@link org.springframework.core.type.filter.TypeFilter} implementation.
*/
CUSTOM
}
-
Filter,聲明類型過濾器,該過濾器將會作爲 include filter or exclude filter 來使用。
-
includeFilters,(指定掃描的時候只包含哪些組件)
進一步將候選組件從 basePackages 全部範圍內縮小到只有在 basePackages 範圍內匹配給定 filter or filters 才能包含。
需要注意的是,如果指定了有includeFilters,那麼除了默認的過濾器,這些includeFilters也會應用進來。
在指定basePackages下的任何類型只要是能夠匹配到給定的filter就會包含進來
儘管它並沒有匹配到default filters(也就是沒有標識 @Component 註解) -
excludeFilters,(指定掃描的時候按照什麼規則排除哪些組件)
-
useDefaultFilters,表示是否自動檢測標註有 @Component @Repository, @Service, or @Controller 的類
-
FilterType,過濾器類型,枚舉類
- FilterType#ANNOTATION,按照註解的形式
- FilterType#ASSIGNABLE_TYPE,按照給定的類型
- FilterType#ASPECTJ,使用ASPECTJ表達式的形式
- FilterType#REGEX,使用正則表達式
- FilterType#CUSTOM,使用給定的自定義過濾器,需要實現TypeFilter接口