Spring源码学习笔记(3)——容器的功能扩展
时间:2022-07-24
本文章向大家介绍Spring源码学习笔记(3)——容器的功能扩展,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
Spring源码学习笔记(3)——容器的功能扩展
一. 引入ApplicationContext接口
- 前面的介绍都是基于BeanFactory接口和它的默认实现XmlBeanFactory的,但是Spring体系中还有一个重要的接口:ApplicationContext。ApplicationContext在BeanFactory上进行了一些扩展,功能更为强大。可以理解为:BeanFactory是Spring容器内部使用的,而ApplicationContext是暴露给应用使用的。除非在一些特殊情况下,否则Spring建议使用ApplicationContext接口的实现类。
- 示例程序 以一段几乎每个Java程序员都写过的代码为例:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
- ClassPathXmlApplicationContext可以支持多个配置路径,在setConfigLocations()方法中进行处理,后续功能都在refresh()方法中:
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
//设置配置路径
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
- 下面重点分析refresh()方法。
二. 整体流程
- refresh()的实现在AbstractApplicationContext类中,这是ApplicationContext体系中十分重要的一个方法,在整体上定义了ApplicationContext容器的启动流程:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//准备带刷新的上下文环境
prepareRefresh();
//初始化BeanFactory,并读取Spring配置文件
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//对初始化BeanFactory进行各种功能的填充
prepareBeanFactory(beanFactory);
try {
//提供给子类的模板方法,可做额外处理
postProcessBeanFactory(beanFactory);
//激活容器中注册的处理器,进行各种处理
invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPosyProcesor后处理器,拦截Bean的创建过程。这里只是注册,并未执行
registerBeanPostProcessors(beanFactory);
//为容器初始化各种Message源,即多语言、国际化处理
initMessageSource();
//初始化消息广播器,将applicationEventMulticaster注册到单例容器中,为容器的消息机制做准备
initApplicationEventMulticaster();
//提供给子类的模板方法,可初始化其他Bean
onRefresh();
//在所有注册的Bean中查找Listener Bean,注册到消息广播器applicationEventMulticaster中
registerListeners();
//初始化剩余的单例Bean(非lazy-init的)
finishBeanFactoryInitialization(beanFactory);
//最后一步:完成容器刷新过程,通知容器中的LifecycleProcessor刷新完成,并且发布ContextRefreshedEvent容器刷新完成事件
finishRefresh();
}
//异常处理
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
//清空Spring通用缓存
resetCommonCaches();
}
}
}
- 可以看到,整个refresh()的流程是很清晰的,处理异常处理外,大概做了这么几件事:
- 初始化前的准备工作,例如对系统属性或者环境变量进行准备及验证。 在某些情况下,项目的运行需要读取某些系统变量,这些变量的设置可能会影响系统的正确性,此时prepareRefresh()这个方法就可以发挥它的作用,在容器启动时(一般也是项目启动时)为我们检查这些变量的设置。
- 初始化BeanFactory,并读取XML配置文件 在这一步中会复用BeanFactory的读取配置文件和加载Bean的过程,在这一步之后,ApplicationContext实际上就包含了所有BeanFactory所提供的功能,可以进行Bean的提取等工作了。
- 对BeanFactory进行各种功能的填充
- 提供给子类模板方法,做额外的扩展
- 激活各种FactoryBean进行处理
- 注册BeanPostProcessor后处理器,这里只是注册,真正调用是在getBean()时
- 为上下文初始化Message源,处理多语言和国际化
- 初始化应用消息广播器ApplicationEventMulticaster,为Spring消息机制做准备
- 提供给子类模板方法,初始化其他的Bean
- 在所有注册的Bean中查找ApplicationListener,注册到ApplicationEventMulticaster
- 初始化其余的非延迟加载的单实例Bean
- 完成容器刷新过程,通知LifecycleProcessor,并发布ContextRefreshedEvent容器刷新完成事件
- 下面仔细分析具体每一步的处理逻辑
三. 环境准备
- 查看方法实现:
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
//初始化placeholder属性源,默认空实现,留给子类覆盖
initPropertySources();
//校验所有需要的属性文件是否都已经放入环境中
getEnvironment().validateRequiredProperties();
//为early的容器事件做准备
this.earlyApplicationEvents = new LinkedHashSet<>();
}
- 这个方法的核心逻辑默认都是空实现,可以交给子类去覆盖,例如我们可以自定义一个ApplicationContext,并且校验自己的属性文件和系统变量配置
四. 加载BeanFactory
- 前面说过,ApplicationContext是对BeanFactory功能上的扩展,不但包含了BeanFactory的全部功能,更是在其基础上添加了大量的扩展应用,obtainFreshBeanFactory()正是实现了BeanFactory的地方,在这个方法之后,ApplicationContext方法就拥有了BeanFactory的全部功能。代码实现:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//初始化BeanFactory,并进行XML文件读取,而且将得到的BeanFactory记录在当前实体的属性中
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
- 核心逻辑委托给了AbstractRefreshableApplicationContext的refreshBeanFactory()方法实现:
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
//创建DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//指定序列化id,如果需要的话,可以根据序列化id反序列化出BeanFactory对象
beanFactory.setSerializationId(getId());
//定制BeanFactory相关属性,
customizeBeanFactory(beanFactory);
//初始化DocumentReader,进行配置文件的读取和解析
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
- refreshBeanFactory()的具体步骤:
- 创建DefaultListableBeanFactory DefaultListableBeanFactory是比较基础的BeanFactory类型。
- 设置序列化id。
- 定制BeanFactory,是对BeanFactory的扩展,在基本容器的基础上,增加了是否允许覆盖和是否允许循环引用的支持。
- 读取配置文件,加载BeanDefinition,该方法交给子类重写,如AbstractXmlApplicationContext类中实现了读取XML文件加载BeanDefinition的处理。
- 使用全局变量beanFactory记录BeanFactory实例
五. 对初始化好的BeanFactory进行各种功能的填充
- 对于上面初始化好的BeanFactory,进行一些属性的设置和功能上的扩展,具体逻辑在prepareBeanFactory()中:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//设置BeanFactory的ClassLoader为当前ApplicationContext的ClassLoader
beanFactory.setBeanClassLoader(getClassLoader());
//设置BeanFactory的表达式语言处理器,支持表达式语言
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//为BeanFactory设置一个默认的PropertyEditor,这个主要是对Bean的属性等设置管理的一个工具
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//添加后处理器
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//设置几个忽略自动装配的接口
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
//设置几个自动装配的特殊规则
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
//增加AspectJ的支持
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
//注册默认的系统Bean
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
- 该方法主要对BeanFactory进行了以下几个方面的扩展:
- 对SPEL表达式的支持
- 对属性编辑器的支持
- 增加对一些内置类,如EnvironmentAware、MessageSourceAware的信息注入
- 对AspectJ的支持
六. BeanFactory的后处理
- BeanFactoryPostProcessor 在BeanFactory的定制化完成之后,开始执行BeanFactory的后处理,后处理主要依赖BeanFactoryPostProcessor类进行。BeanFactoryPostProcessor的功能类似于BeanPostProcessor,可以对Bean的定义(配置元数据)进行处理,也就是说,Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何其他的Bean之前读取配置元数据,并可能修改它。BeanFactoryPostProcessor与BeanPostProcessor的主要区别在于,BeanFactoryPostProcessor是容器级别的,它的处理依赖于当前的BeanFactory,而且不要通过BeanFactoryPostProcessor进行Bean实例化的相关处理,BeanFactoryPostProcessor只能处理BeanDifinition。
- 激活BeanFactoryPostProcessor 下面回到refresh()方法的处理,调用invokeBeanFactoryPostProcessors()激活容器中注册的BeanFactoryPostProcessor:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
- 核心方法为PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()),调用容器中所有注册的BeanFactoryPostProcessor的postProcessBeanFactory()方法。
七. 注册BeanPostProcessor
- ApplicationContext在registerBeanPostProcessors()方法中注册了BeanPostProcessor,这里只是注册,并不是调用,真正的调用实在创建Bean的时候处理的。这是一个重要的步骤,也是BeanFactory不支持BeanPostProcessor的原因:BeanFactory中没有实现后处理器的自动注册,只能手动注册。
- 具体实现:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//获取所有BeanPostProcessor的Bean Name
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
//向容器中注册BeanPostProcessorChecker后处理器,只是一个普通的打印
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
//使用priorityOrderedPostProcessors保证顺序
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
//使用orderedPostProcessorNames保证顺序
List<String> orderedPostProcessorNames = new ArrayList<>();
//无序的BeanPostProcessors
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
//1.排序,注册所有实现了PriorityOrdered接口的有序BeanPostProcessor
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
//2.排序,注册所有实现了Ordered接口的有序BeanPostProcessor
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
//3.注册无序的BeanPostProcessor
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
//最后,注册实现了MergedBeanDefinitionPostProcessor接口的BeanPostProcessor
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
//注册ApplicationListenerDetector探测器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
八. 后续步骤
- 初始化消息资源
- 初始化ApplicationEventMulticaster,为Spring的Event体系提供支持。 当发布容器事件时,会默认使用SimpleApplicationEventMulticaster对事件进行广播,遍历所有的ApplicationListener,回调ApplicationListener的onApplicationEvent()方法处理事件。每个监听器都可以监听到容器发布的所有事件,但是是否处理由监听器逻辑决定。
- 注册监听器 上面提到的Event体系中的监听器,就是在这里注册的。
- 初始化非延迟加载的单例Bean
- 容器刷新完成
- 10.22 firewalld关于service的操作
- 10.21 firewalld关于zone的操作
- 逆向专题 | Writeup分享一
- SPI框架实现之旅三:实现说明
- 10.20 firewalld的9个zone
- 英语不好,数学也不好,能不能学WEB前端?
- 10.19 iptables规则备份和恢复
- 11.6 MariaDB安装
- cocos2dx-v3.4 2048(四):游戏逻辑的设计与实现
- Linux基础(day39)
- Chrome扩展程序之编码&时间戳小工具
- WINDOWS下烧一只鹅
- 11.3/11.4/11.5 MySQL安装
- Greenrobot-EventBus源码学习(六)
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释