Spring Boot 自动配置 源码分析

Spring Boot 最大的特点(亮点)就是自动配置 AutoConfiguration

下面,先说一下 @EnableAutoConfiguration ,然后再看源代码,到底自动配置是怎么配置的

1.  @EnableAutoConfiguration

@SpringBootApplication是一个复合注解,本节我们重点关注 @EnableAutoConfiguration

自动配置类是常规的Spring @Configuration bean。它们使用SpringFactoriesLoader机制定位。通常,自动配置bean是@Conditional Bean(最经常使用@ConditionalOnClass和@ConditionalOnMissingBean注解)

在@EnableAutoConfiguration注解上有一个@Import注解

@Import这个注解表明要导入的一个或多个组件类,通常是@Configuration类。

@Import注解提供与Spring XML中的<import />元素等效的功能。允许导入@Configuration类,ImportSelector和ImportBeanDefinitionRegistrar实现以及常规组件类。

根据导入的@Configuration类的AnnotationMetadata,返回AutoConfigurationImportSelector.AutoConfigurationEntry。

方法的参数AnnotationMetadata代表配置类上的注解元数据,方法的返回值是应该被导入的自动配置类

首先,获取配置类上的注解的属性

又是熟悉的方法:SpringFactoriesLoader.loadFactoryNames() 

在所有 META-INF/spring.factories 文件中查找 org.springframework.boot.autoconfigure.EnableAutoConfiguration

然后,去重

然后,再排除一些,根据注解属性中明确指定的exclude

删除所有需要排除的

然后,过滤掉一些不需要的

根据对所有的需要自动配置的类应用那三个过滤器

最终剩下的就是真正需要导入的,或者说真正需要自动配置的

在众多需要自动配置的类中,我们挑一个熟悉的来看一下,就挑org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

看这注解,当classpath中有RedisOperations时才会自动配置该类,当有RedisConnectionFactory且没有redisTemplate时才会创建一个redisTemplate,同理,有RedisConnectionFactory且没有stringRedisTemplate时才会创建一个stringRedisTemplate

回顾一下

1、在所有 META-INF/spring.factories 文件中查找 org.springframework.boot.autoconfigure.EnableAutoConfiguration,返回一个List<String>

2、对上一步返回的List去重

3、根据注解exclude属性排除List中的一些元素

4、根据AutoConfigurationImportFilter过滤掉一些不需要自动配置的元素

5、讲过以上四步,List中剩下的元素就是最终需要自动配置的元素(类)

至此,只是筛选出了哪些类需要自动配置,但还没有真正装配(实例化),真正实例化Bean是在Spring Boot启动时刷新ApplicationContext时做的

注解只是个标记,是给反射用的,有注解必然有处理它的类

接下来,分析源码,看看究竟什么时候开始真正自动装配

2.  Spring Boot 自动配置源码分析

又来到了熟悉的SpringApplication.run()方法这里,这一次,重点看其中的三步:createApplicationContext()、prepareContext() 和 refreshContext()

首先看createApplicationContext()

看看AnnotationConfigServletWebServerApplicationContext有多复杂

创建了两个BeanDefinition分别是AnnotatedBeanDefinitionReader 和 ClassPathBeanDefinitionScanner,它们都是用来查找并加载Bean定义的,只是方式不同而已

下面重点看一下AnnotatedBeanDefinitionReader

(PS:其实,这里注册了很多BeanPostProcessor,有处理Autowired的AutowiredAnnotationBeanPostProcessor,由于本节主要讲自动配置的,所以我们重点关注ConfigurationClassPostProcessor)

先做个笔记:

1、ApplicationContext 是 AnnotationConfigServletWebServerApplicationContext

2、构造了一个AnnotatedBeanDefinitionReader,大家要明白BeanDefinitionReader是用来加载Bean定义的

3、把这个AnnotatedBeanDefinitionReader注册(关联)到该ApplicationContext

4、在构造AnnotatedBeanDefinitionReader的时候注册了很多Processors

可见AnnotatedBeanDefinitionReader真的是相当相当重要,而重中之重是org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors()

我们单独把这段拿出来再看一下

如果没有这个BeanDefinition的时候就添加一个

CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 对应的是 ConfigurationClassPostProcessor

先记住这一点,后面会用到

接下来,看prepareContext()

 

重点看SharedMetadataReaderFactoryContextInitializer

好,记住这一点,此处添加了一个BeanFactoryPostProcessor,它是一个CachingMetadataReaderFactoryPostProcessor

最后,再来看refreshContext()

调用是Spring的refresh()

 

重点看 invokeBeanFactoryPostProcessors 调用所有已注册的BeanPostProcessor

这里,调用getBeanFactoryPostProcessors()返回的BeanFactoryPostProcessors中有CachingMetadataReaderFactoryPostProcessor

好,记住这一点

继续看PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()

好,看CachingMetadataReaderFactoryPostProcessor#postProcessBeanDefinitionRegistry()

又看到了熟悉的AnnotationConfigUtils.CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME,我们知道它是ConfigurationClassPostProcessor

回到PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()继续往下看

得到ConfigurationClassPostProcessor

接下来,调用postProcessBeanDefinitionRegistry

方法太长,就不截全图了,总之就是找到配置类,开始解析配置类了,只看重点

到这里终于和我们前面讲的@EnableAutoConfiguration自动配置开始沾点儿边了

下面,重点来了,核心中的核心

终于写完了,累死我了

 

给TA买糖
共{{data.count}}人
人已赞赏
经验教程

Elasticsearch 复合查询——多字符串多字段查询

2021-3-14 16:24:00

经验教程

设计模式之建造者模式(BuilderPattern)

2021-3-14 16:37:00

⚠️
免责声明:根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。 本站为个人博客非盈利性站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途,网站会员捐赠是您喜欢本站而产生的赞助支持行为,仅为维持服务器的开支与维护,全凭自愿无任何强求。本站部份代码及教程来源于互联网,仅供网友学习交流,若您喜欢本文可附上原文链接随意转载。
无意侵害您的权益,请发送邮件至 momeis6@qq.com 或点击右侧 私信:momeis 反馈,我们将尽快处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索