Spring容器技术内幕
1.内部工作机制
Spring的AbstractApplicationContext是ApplicationContext的抽象实现类,该抽象类的reflesh方法定义了Spring容器在加载配置文件后的各项处理过程,这些处理过程清晰地刻画了Spring容器启动时所执行的各项操作,方法如下所示:
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
// 1.初始化bean工厂
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
// 2.调用工厂后处理器
this.invokeBeanFactoryPostProcessors(beanFactory);
// 3.注册bean后处理器
this.registerBeanPostProcessors(beanFactory);
// 4.初始化消息源
this.initMessageSource();
// 5.初始化应用上下文事件广播器
this.initApplicationEventMulticaster();
// 6.初始化其他特殊的bean,有 具体子类实现
this.onRefresh();
// 7.注册事件监听器
this.registerListeners();
// 8.初始化所有单实例的bean,使用懒加载模式的bean除外
this.finishBeanFactoryInitialization(beanFactory);
// 9.完成刷新并发布容器刷新事件
this.finishRefresh();
} catch (BeansException var9) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var9);
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
- 初始化BeanFactory:根据配置文件实例化BeanFactory,在obtainFreshBeanFactory()方法中,首先调用refleshBeanFactory方法刷新BeanFactory,然后调用getBeanFactory()方法获取BeanFactory,这两个方法都是由具体子类实现的 。在这一步,Spring将配置文件的信息装入容器的Bean定义注册表(BeanDefinitionRegistry)中,但此时Bean还未初始化
- 调用工厂后处理器:根据反射机制从BeanDefinitionRegistry中找出所有实现了BeanFactoryPostProcessor接口的bean,并调用其postProcessBeanFactory方法接口方法。
- 注册bean后处理器:根据反射机制从BeanDefinitionRegistry中找出所有实现类BeanPostProcessor接口的bean,并将它们注册到容器Bean后处理器的注册表中
- 初始化消息源:初始化容器的国际化消息资源
- 初始化应用上下文事件广播器
- 初始化其他特殊的bean:这是一个钩子方法,子类可以借助这个方法执行一些特殊的操作,如AbstractRefreshableWebApplicationContext就使用执行初始化ThemeSource的 操作
- 注册事件监听器
- 初始化所有单实例的bean,使用懒加载模式的bean除外:初始化bean后,将他们放在Spring的容器缓存池中
- 发布上下文刷新事件:创建上下文刷新事件,事件广播器负责将这些事件广播到每个注册的事件监听器中
2.Spring从加载配置文件到创建一个完整的bean的作业流程
- ResourceLoader从存储介质中加载Spring配置信息,并使用Resource表示这个配置文件的资源
- BeanDefinitionReader读取Resource所指向的配置文件资源,然后解析配置文件。配置文件中的每个bean解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中
- 容器扫描BeanDefinitionRegistry中的BeanDefinition,使用java反射机制自动识别出Bean工厂后处理器(实现了BeanFactoryPostProcessor接口的bean),然后调用这些bean工厂后处理器对BeanDefinitionRegistry中的BeanDefinition进行加工处理主要完成一下 两项工作
- 对使用占位符的<bean>元素标签进行解析,得到最终的配置值。这意味着对一些半成品的BeanDefinition对象进行加工处理并得到成品的BeanDefinition对象
- 对BeanDefinitionRegistry中的BeanDefinition进行扫描,通过java反射机制找到所有的属性编辑器的bean(实现了java.beans.PropertyEditor接口),并自动将它们注册到Spring容器的属性编辑器注册表中(PropertyEditorRegistry)
- spring从BeanDefinitionRegistry中去除加工后的BeanDefinition,并调用InstantiationStrategy着手进行bean的实例化工作
- 在实例化bean时,Spring容器使用BeanWrapper对bean进行 封装,BeanWrapper提供了以java反射操作bean的方法,它将结合该bean的BeanDefinition和容器中的属性编辑器,完成bean的注入工作
- 利用容器中注册的bean后处理器(实现了BeanPostProcessor)对已经完成属性设置工作的bean进行后续加工,直接装配出一个准备就绪的bean