Spring源码剖析之@Configuration核心配置类解析

准备

在这里插入图片描述
在这里插入图片描述

refresh 方法

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 刷新前预处理
			prepareRefresh();

			// 获取之前创建的BeanFactory,默认实现DefaultListableBeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,设置类加载器,环境等等。
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);
				
				//  实例化并调用默认配置,和自定义的BeanFactoryPostProcessor,实现核心配置类解析,包组件扫描封装BeanDefinition.
				invokeBeanFactoryPostProcessors(beanFactory);

				// 注册默认配置的和自定义的BeanPostProcessor , 实现bean创建赋值之后 init 方法前后调用
				registerBeanPostProcessors(beanFactory);

				// 初始化MessageSource组件,实现 国际化功能,消息绑定,消息解析
				initMessageSource();

				// 初始化应用事件派发器
				initApplicationEventMulticaster();

				// 子类重写
				onRefresh();

				// 注册实现了ApplicationListener接⼝的监听器
				registerListeners();

				// 实例化剩下的所有单例bean
				finishBeanFactoryInitialization(beanFactory);

				// 发布事件,交由其它组件触发对应响应,例如springMVC初始化
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}

注意这个invokeBeanFactoryPostProcessors(beanFactory); 方法。

在这里插入图片描述
注意此时IOC容器中的BeanDefinitionMap中已经存在一些系统默认的,和核心配置类BeanDefinition

在这里插入图片描述

点击去发现,这里先调用 实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors

在这里插入图片描述
然后调用实现了Ordered的BeanDefinitionRegistryPostProcessors

在这里插入图片描述

最后调用其它剩余的BeanDefinitionRegistryPostProcessors。

在这里插入图片描述

从实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors开始剖析,从BeanDefinitionMap中获取实现该接口的BeanDefinition(ConfigurationClassPostProcessor),然后实例化,接着调用postProcessor方法

ConfigurationClassPostProcessor 主要实现对 @Configuration的核心配置类进行解析

在这里插入图片描述

ConfigurationClassPostProcessor 处理流程

1、从当前的BeanDefinitionMap中找到满足@Configuration的BeanDefinition

在这里插入图片描述

2、解析满足的每一个@Configuration类,而当前满足条件的@Configuration类是我们自己定义的核心配置类

在这里插入图片描述

3、解析我们配置的核心配置类,如果存在父类依次进行解析
在这里插入图片描述

4、正式解析@Configuration所在类

4.1、解析@PropertySource注解,实现外部配置文件加载

在这里插入图片描述

4.2、解析@ComponentScan注解,实现指定包下的组件扫描

在这里插入图片描述

4.2.1、获取@ComponentScan所有的属性,以basePackage为例
4.2.2、解析basePackage后面的包,对指定包进行扫描

在这里插入图片描述
4.2.3 获取编译后的target目录+ 我们直接指定的包路径 = 最终.class文件存在的位置。
将目标包,极其子包对应的组件,全部封装成BeanDefinition

在这里插入图片描述
找到目标包路径
在这里插入图片描述

封装BeanDefinition

在这里插入图片描述

最终可以获取到指定包下的所有组件BeanDefinition

在这里插入图片描述

4.3、解析@Import注解,实现其它配置文件载入

在这里插入图片描述

4.5、解析@Bean注解,通过 getAnnotatedMethods(Bean.class.getName()) 获取@Bean对应的所有方法
在这里插入图片描述

在这里插入图片描述

到此为止,spring对于启动时,定义的核心配置解析完成,对应的组件扫描也完成。这些组件都会被注册到IOC容器中BeanDefinitionMap当中

总结

spring如何对@Configuration定义的核心配置类进行解析?

1、在容器BeanFactory创建完成后,调用invokeBeanFactoryPostProcessor
2、invokeBeanFactoryPostProcessor中有一个实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors(简称ConfigurationClassPostProcessor),实现对我们定义的核心配置类进行解析
3、解析@PropertySource,@Import,@ComponentScan,@Bean。
以@ComponentScan解析为例,获取当前项目编译后的target路径 + 自定义包路径 = 最终.class文件,将存在@Component等注解的组件,全部封装成BeanDefinition,放入IOC容器的BeanDefinitionMap当中,等待实例化。

解析流程为什么从核心配置类开始

1、我们使用AnnotationConfigApplicationContext来创建和启动容器,那么默认加载核心配置文件,成BeanDefinition,放入容器

ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(ApplicationContextConfiguration.class);

2、而在invokeBeanFactoryPostProcessor中通过ConfigurationClassPostProcessor,实现对@Configuration进行解析,那么@Cofiguration对应的类,默认是从BeanDefinitionMap中获取,此时只有我们定义的核心配置类,因此从核心配置类开始组件扫描解析。

在SpringBoot中也是从启动类开始解析的,例如启动类上的@SpringBootApplication

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白鸽呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值