本文章仅用于本人学习笔记记录
来源《SpringBoot 源码解读与原理分析》
微信:A20991212A(如本文档内容侵权了您的权益,请您通过微信联系到我)
@SpringBootApplication
启动类上@SpringBootApplication注解源码
/**
* ......
* @since 1.2.0
*/
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication文档注释原文翻译:
Indicates a configuration class that declares one or more @Bean methods and also triggers auto-configuration and component scanning. This is a convenience annotation that is equivalent to declaring
@Configuration, @EnableAutoConfiguration and @ComponentScan.
标识了一个配置类,这个配置类上声明了一个或多个 @Bean 的方法,并且它会触发自动配置和组件扫描。
这是一个很方便的注解,它等价于同时标注 @Configuration + @EnableAutoConfiguration + @ComponentScan 。

@ComponentScan
在SpringFramework中@ComponentScan可以指定包扫描的根路径,让 SpringFramework 来扫描指定包及子包下的组件,也可以不指定路径,默认扫描当前配置类所在包及子包里的所有组件(其实这就解释了为什么 SpringBoot 的启动类要放到所有类所在包的最外层)。
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })声明中有显式的指定了两个过滤条件
TypeExcludeFilter
向IOC容器中注册一些自定义的组件过滤器,以在包扫描的过程中过滤它们。
这种Filter的核心方法是 match 方法,它实现了过滤的判断逻辑:
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
if (this.beanFactory instanceof ListableBeanFactory && getClass() == TypeExcludeFilter.class) {
Collection<TypeExcludeFilter> delegates = ((ListableBeanFactory) this.beanFactory)
.getBeansOfType(TypeExcludeFilter.class).values();
for (TypeExcludeFilter delegate : delegates) {
if (delegate.match(metadataReader, metadataReaderFactory)) {
return true;
}
}
}
return false;
}从 BeanFactory (可以暂时理解成IOC容器)中获取所有类型为 TypeExcludeFilter 的组件,去执行自定义的过滤方法。
由此可见,TypeExcludeFilter 的作用是做扩展的组件过滤。
AutoConfigurationExcludeFilter
注解源码:
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
return isConfiguration(metadataReader) && isAutoConfiguration(metadataReader);
}
private boolean isConfiguration(MetadataReader metadataReader) {
return metadataReader.getAnnotationMetadata().isAnnotated(Configuration.class.getName());
}
private boolean isAutoConfiguration(MetadataReader metadataReader) {
return getAutoConfigurations().contains(metadataReader.getClassMetadata().getClassName());
}
protected List<String> getAutoConfigurations() {
if (this.autoConfigurations == null) {
this.autoConfigurations = SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,
this.beanClassLoader);
}
return this.autoConfigurations;
}match 方法要判断两个部分:是否是一个配置类,是否是一个自动配置类。
@SpringBootConfiguration
@Configuration
public @interface SpringBootConfiguration文档注释原文翻译:
Indicates that a class provides Spring Boot application @Configuration . Can be used as an alternative to the Spring’s standard @Configuration annotation so that configuration can be found automatically (for example in tests).
Application should only ever include one @SpringBootConfiguration and most idiomatic Spring Boot applications will inherit it from @SpringBootApplication.
标识一个类作为 SpringBoot 的配置类,它可以是Spring原生的 @Configuration 的一种替换方案,目的是这个配置可以被自动发现。
应用应当只在主启动类上标注 @SpringBootConfiguration,大多数情况下都是直接使用 @SpringBootApplication。
它被 @Configuration 标注,说明它实际上是标注配置类的,而且是标注主启动类的。
@Configuration的作用
被 @Configuration 标注的类,会被 Spring 的IOC容器认定为配置类。
一个被 @Configuration 标注的类,相当于一个 applicationContext.xml 的配置文件。
例如:声明一个类,并标注 @Configuration 注解:
@Configuration
public class ConfigurationDemo {
@Bean
public Date currentDate() {
return new Date();
}
}上述注册Bean的方式类比于xml:
<bean id="currentDate" class="java.util.Date"/>之后使用注解启动方式,初始化一个IOC容器,并打印IOC容器中的所有bean的name:
public class MainApp {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigurationDemo.class);
String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
Stream.of(beanDefinitionNames).forEach(System.out::println);
}
}输出结果:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
configurationDemo
currentDate可以发现组件,以及配置类本身被成功加载。
总结
- @SpringBootApplication 是组合注解。@SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan
- @ComponentScan 默认扫描当前配置类所在包及子包下的所有组件,提供TypeExcludeFilter和AutoConfigurationExcludeFilter。
- @SpringBootConfiguration 可标注配置类,@SpringBootConfiguration 并没有对@Configuration做实质性扩展。