一、 @SpringBootApplication注解
进入@SpringBootApplication发现其包含3个注解,分别为@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
(1)@SpringBootConfiguration注解用于标注Spring应用引导类,在应用启动的时候这个引导类会被执行;
(2)@EnableAutoConfiguration注解用于根据依赖自动开启一些配置;
(3)@ComponentScan注解用于配置哪些基础包或类被自动扫描。
二、@EnableAutoConfiguration注解
1.EnableAutoConfiguration作用
其用于类或接口上。
当spring boot扫描到@EnableAutoConfiguration注解时则会将
META-INF/spring.factories文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的value里的所有xxxConfiguration类(value值是一个列表,列表中记录的是需要进行自动化配置的类会被执行,例如AopAutoConfiguration会自动配置Aop相关配置,使用JDK代理还是CGLIB代理)加载到IOC容器中。即value是类的全路径,多个用逗号分隔。
而xxxAutoConfiguration类一般都会有@ConditionalOnxxx注解,通过这些条件注解来判断是否真正的创建xxxConfiguration对象。
spring boot的各种spring-boot-starter-xxx.jar也正是居于此注解来达到自动装配的目的。
spring.factories内容如下:
@ConditionalOnxxx常见注解如下:
2.那这个自动化配置是如何触发的?
spring boot自动装配的过程都是在ConfigurationClassPostProcessor这个类中完成的。
从源码执行顺序角度进行分析:
public class ConfigurationClassPostProcessor {
…………
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
//1、该方法执行完后会将/META-INF/spring.factories文件
//中org.springframework.boot.autoconfigure.EnableAutoConfiguration
//对应的value值全部封装
//成ConfigurationClass对象存在parser对象的configurationClasses属性中。
parser.parse(candidates);
parser.validate();
//2、取出ConfigurationClass对象
configClasses.removeAll(alreadyParsed);
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//3、将ConfigurationClass转换成ConfigurationClassBeanDefinition
//并注册到beanFactory中,以供后面创建具体的对象
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
…………
}
而BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor接口,熟悉Spring原理的都知道BeanFactoryPostProcessor接口中的postProcessBeanFactory方法会在Spring容器加载bean的定义文件之后,在bean实例化之前执行,而这一步是由SpringApplication的run方法触发的,在这个run方法中实现了Spring容器的启动及初始化。
三、@ComponentScan注解
1.作用
@ComponentScan用于类或接口上主要是指定扫描路径,spring会把指定路径下带有指定注解的类自动装配到bean容器里。会被自动装配的注解包括@Controller、@Service、@Component、@Repository等等。其作用等同于<context:component-scan base-package=“com.maple.learn” />配置。
2.@ComponentScan使用
常用属性如下:
basePackages:指定扫描路径,如果为空则以@ComponentScan注解的类所在的包为基本的扫描路径
basePackageClasses:指定具体扫描的类
includeFilters:指定满足Filter条件的类
excludeFilters:指定排除Filter条件的类
includeFilters和excludeFilters 的FilterType可选:ANNOTATION=注解类型 默认、ASSIGNABLE_TYPE(指定固定类)、ASPECTJ(ASPECTJ类型)、REGEX(正则表达式)、CUSTOM(自定义类型),自定义的Filter需要实现TypeFilter接口。
@ComponentScan的常见的配置如下:
比如:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//.......省略若干代码........
}
3.原理总结如下:
1、扫描@ComponentScan注解包下面的所有的可自动装备类,生成BeanDefinition对象,并注册到beanFactory对象中。
2、通过DeferredImportSelectorHandler处理@EnableAutoConfiguration注解,后续会有专文介绍。
3、将带有@Configuration 注解的类解析成ConfigurationClass对象并缓存,后面创建@Bean注解的Bean对象所对应的BeanDefinition时会用到。