1. 关于@SpringBootApplication

我们在用 SpringBoot 项目进行开发时,在启动类中会发现这样一个注解:@SpringBootApplication。进入源码中查看,这个注解又用到了其他三个注解:

SpringBootApplication注解源码

  • @SpringBootConfiguration:进入它的源码,发现它用到了一个核心注解 @Configuration ,表示当前类是一个配置类,通过 @Configuration 与 @Bean结合,可以将 Bean 注册到 ioc 容器。

  • @ComponentScan:因为这里它没有指定扫描的包,因此它会默认扫描与启动类同级的类或者同级包下的所有类。

  • 这里着重讲一下 @EnableAutoConfiguration 注解:

一旦加上此注解,那么将会开启自动装配功能,简单点讲,Spring 会试图在项目的 classpath 下找到所有配置的Bean 然后进行装配。当然装配Bean时,会根据若干个(Conditional)定制规则来进行初始化。

我们来看一下它的源码:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

这里比较重要的是 AutoConfigurationImportSelector 类:

首先该类实现了DeferredImportSelector接口,这个接口继承了ImportSelector,该接口主要是为了导入 @Configuration 的配置项,而 DeferredImportSelector 是延期导入,只有当所有的 @Configuration 都处理过后才会执行。

我们再来看一下 AutoConfigurationImportSelector的 selectImports 方法:

该方法刚开始会先判断是否要进行自动装配,而后会从 META-INF/spring-autoconfigure-metadata.properties 读取元数据与元数据的相关属性,紧接着会调用 getCandidateConfigurations 方法:

这里有个我们熟悉的 SpringFactoryiesLoader, 它会读取 META-INF/spring.factories 下的EnableAutoConfiguration 配置,紧接着再进行排除与过滤,得到需要装配的类。

最后让所有配置在 META-INF/spring.factories 下的 AutoConfigurationImportListener 执行 AutoConfigurationImportEvent 事件,告诉条件评估报告器对象(ConditionEvaluationReport )来分别记录符合条件和 exclude 的自动配置类,最后再将筛选后的自动配置类注入 IOC 容器中。

2. 什么时候进行自动装配

在前面的步骤里只是确定哪些类需要被装配,那什么时候会处理这些自动装配的类呢?

来看看 AbstractApplicationContext 类的 refresh 方法,它是 Spring 容器启动的主流程方法。里面有一个 invokeBeanFactoryPostProcessors 方法,这个方法会处理 bean 中的各种注解,其中包含了 @Bean 的解析

ConfigurationClassPostProcessor 类主要是处理 @Configuration 注解的,它实现了 BeanDefinitionRegistryPostProcessor类,也间接的实现了BeanFactoryPostProcessor。该类里面有一个processConfigBeanDefinitions 方法,而解析每个 @Configuration 类的关键是 ConfigurationClassParser类里的 parse方法。

在 process 里将会对 DeferredImportSelector 进行处理,然后进行自动装配。

最后总结一下:

  1. springboot 的自动装配利用了 SpringFactoriesLoader 来加载 META-INF/spring.factoires 文件里配置的所有EnableAutoConfgruation,它会经过 exclude 和 filter 等操作,最终决定需要装配哪些类到 IOC容器中。
  2. 处理 @Configuration 的核心是 ConfigurationClassPostProcessor 类,它实现了BeanDefinitionRegistryPostProcessor 类,也间接实现了 BeanFactoryPostProcessor 。 因此当 AbstractApplicationContext 执行 refresh 方法里的invokeBeanFactoryPostProcessors(beanFactory) 方法时会执行自动装配。

更多推荐

【Springboot面试题】自动装配过程及其原理