江帅帅:精通 Spring Boot 系列 02

江帅帅:精通 Spring Boot 系列 02
1 @SpringBootApplication 注解
Spring Boot 的启动类,也就是入口类,须要使用 @SpringBootApplication 注解来标注。在启动类中,咱们的 main 方法就是 Java 应用程序的入口方法。spring

@SpringBootApplication 是一个组合注解,具体源码以下:框架

江帅帅:精通 Spring Boot 系列 02

江帅帅:精通 Spring Boot 系列 02

其中,比较重要的三个注解是:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan。ide

2 @SpringBootConfiguration 注解spring-boot

主要是负责 Spring Boot 应用配置相关的注解,它也是组合注解,具体源码以下:post

江帅帅:精通 Spring Boot 系列 02

经过源码,能够看到它也使用了 @Configuration 注解,它们两个都是将当前类标注为配置类,能将类中使用 @Bean 注解标记的方法对应的实例注入到 Spring 容器中,那实例名就是方法名。3d

另外在 @Configuration 注解源码中,还看到有一个 @Component 注解,作了再次封装,主要是把普通 POJO 实例化到 Spring 容器中。具体源码以下:
江帅帅:精通 Spring Boot 系列 02对象

因此,更推荐你们在 Spring Boot 应用中使用 @SpringBootConfiguration。blog

3 @EnableAutoConfiguration 注解接口

主要用来启动自动配置,Spring Boot 就可以根据依赖信息自动实现应用的相关配置,整体分为两个部分:一是收集全部 spring.factories 中EnableAutoConfiguration 相关 bean 的类,二是将获得的类注册到 Spring 容器中。将符合的配置都加载到 IoC 容器中。具体源码以下:get

江帅帅:精通 Spring Boot 系列 02

组件调用关系图,具体以下:

江帅帅:精通 Spring Boot 系列 02

这张图,怎么去理解呢?实际上是这样的,涉及到了 BeanFactory 的建立。Spring 框架中会调用 ApplicationContext 的 refresh 方法来启动 Spring 容器,而后就会建立 BeanFactory,接着扫描各类包,读取使用到了 @Configuration、@Import、@SpringBootApplication 等注解标注的类,而后生成 BeanDefinition 最终注册到 BeanFactory 中。

而后就交给 BeanFactoryPostProcessor 来执行,BeanFactory 后置处理器会处理 BeanDefinition,好比在 BeanFactoryPostProcessor 接口中,提供了 postProcessBeanFactory 方法来接收 ConfigurableListableBeanFactory 对象来处理。具体源码以下:
江帅帅:精通 Spring Boot 系列 02

其余相似 @Configuration 等配置性质的注解,就让 ConfigurationClassPostProcessor 来处理。

上面的 ConfigurationClassPostProcessor 主要是 BeanFactoryPostProcessor 接口的实现类,主要是想从 BeanFactory 中获取全部 BeanDefinition 列表,遍历出那些使用了 @Configuration、@Import 等配置性质注解标注的类所对应的 BeanDefintion,而后进行注册。具体源码以下:
江帅帅:精通 Spring Boot 系列 02
江帅帅:精通 Spring Boot 系列 02

具体,咱们还能够去看看它的 parse 方法是如何处理的,它会去解析注解。

江帅帅:精通 Spring Boot 系列 02

看到最后的 deferredImportSelectorHandler,这个内部类的里面有一个 deferredImportSelectors 集合,主要是用来添加 AutoConfigurationImportSelector。这个内部私有类,主要维护了一个类型为DeferredImportSelectorHolder 的 deferredImportSelectors 列表。这最后一句代码,就是处理完其余BeanDefinitions 后调用 process 方法。

再接着来看 process 方法,它负责自动配置类导入的内部实现,具体源码以下:

江帅帅:精通 Spring Boot 系列 02

这个方法,须要这么来理解:

首先,DeferredImportSelector 它会去从 spring-boot-autoconfigure 包路径下的 META-INF/spring.factories 文件中找到 EnableAutoConfiguration 做为 key,而后获取对应的自动配置类列表。

第二步,在里面经过 key 便可找到对应须要自动配置的类。接着会进行遍历全部类名,加载和导入对应的配置类。

大体的思路是会先建立一个 ConfigurationClass 的对象,它会包含当前这个配置类,而后传进被调用的 doProcessConfigurationClass 方法中,而后处理该类包含的注解。若是是 @Import 注解,则会放在 processImports 方法中进行处理。

再具体讲,就是那些非 ImportSelector 接口实现类和ImportBeanDefinitionRegistrar 接口实现类的配置类,就会调用processConfigurationClass 方法来处理该自动配置类上面的其余注解,并将该自动配置类内部使用了 @Bean 注解的全部方法,条件化生成 bean 并注册到 Spring 容器,那最终就能够提供特定功能组件的默认实现,也就实现了 SpringBoot 的自动配置功能,在你使用的时候,好比直接经过 @Autowried 注解就能够注入某个功能组件,而不须要显示配置。

具体源码以下(这里不贴所有源码了,你们能够看看它给出的注释就明白了):

江帅帅:精通 Spring Boot 系列 02

4 获取 Bean 类信息
咱们能够来研究下这个注解,了解它是如何加载配置的。在源码中,能够看到 @Import({AutoConfigurationImportSelector.class}) 注解,导入的就是自动配置选择器。

AutoConfigurationImportSelector 选择器是 DeferredImportSelector 接口的实现类,会在 BeanFactory 中对全部 BeanDefinition 处理后执行来进行 SpringBoot 自动配置类的加载、导入操做等,并基于 @Conditional 条件化配置来决定是否将该配置类内部定义的 Bean 注册到 Spring 容器。具体源码以下:

江帅帅:精通 Spring Boot 系列 02

在 AutoConfigurationImportSelector.class 中,能够看到实现了一个 selectImports 方法,用来导出 Configuration。方法中调用了 getAutoConfigurationEntry 方法,获取 bean 类信息。具体源码以下:

江帅帅:精通 Spring Boot 系列 02

继续来看 getAutoConfigurationEntry 方法,具体源码以下:

江帅帅:精通 Spring Boot 系列 02

再接着来看调用的 getCandidateConfigurations 方法,它主要是想获取全部对应的配置,它里面调用了 loadFactoryNames 方法,目的是要想加载 spring.factories 文件。它们的源码具体以下:
江帅帅:精通 Spring Boot 系列 02

loadFactoryNames 方法的具体源码以下:
江帅帅:精通 Spring Boot 系列 02

接着就在 loadSpringFactories 方法中,找到全部的 spring.factories 配置信息,而后所有返回。具体源码以下:
江帅帅:精通 Spring Boot 系列 02

相关文章
相关标签/搜索