【Spring源码核心篇-04】spring中refresh刷新机制的流程和实现
Spring源码核心篇整体栏目
内容 | 链接地址 |
---|---|
【一】Spring的bean的生命周期 | https://zhenghuisheng.blog.csdn.net/article/details/143441012 |
【二】深入理解spring的依赖注入和属性填充 | https://zhenghuisheng.blog.csdn.net/article/details/143854482 |
【三】精通spring的aop的底层原理和源码实现 | https://zhenghuisheng.blog.csdn.net/article/details/144012934 |
【四】spring中refresh刷新机制的流程和实现 | https://zhenghuisheng.blog.csdn.net/article/details/144118337 |
深入理解spring的依赖注入和属性填充
- 一,spring中refresh刷新机制
- 1,prepareRefresh方法
- 2,obtainFreshBeanFactory方法
- 3,prepareBeanFactory方法
- 4,postProcessBeanFactory方法
- 5,invokeBeanFactoryPostProcessors方法
- 6,registerBeanPostProcessors方法
- 7,initMessageSource方法
- 8,initApplicationEventMulticaster方法
- 9,onrefresh方法
- 10,registerListeners方法
- 11,finishBeanFactoryInitialization方法
- 12,finishRefresh方法
如需转载,请附上链接:https://blog.csdn.net/zhenghuishengq/article/details/144118337
一,spring中refresh刷新机制
前面讲解了spring的核心思想AOP和IOC 的底层原理和实现,接下来讲解的是spring源码的核心机制 refresh 方法,不管是前面的aop或者是ioc,都是需要经过这个核心方法的,接下来详细的查看这个refresh这个方法。
如在创建AnnotationConfigApplicationContext ,内部就会涉及到这个refresh方法
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
refresh方法的具体实现如下,刷新时会加一个synchronized锁保证同步,其基本流程如下,接下来在后文会对里面的每一个步骤做一个初步的解释
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//1:准备刷新上下文环境
prepareRefresh();
//2:获取告诉子类初始化Bean工厂 不同工厂不同实现
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//3:对bean工厂进行填充属性
prepareBeanFactory(beanFactory);
try {
// 第四:留个子类去实现该接口
postProcessBeanFactory(beanFactory);
// 调用我们的bean工厂的后置处理器. 1. 会在此将class扫描成beanDefinition 2.bean工厂的后置处理器调用
invokeBeanFactoryPostProcessors(beanFactory);
// 注册我们bean的后置处理器
registerBeanPostProcessors(beanFactory);
// 初始化国际化资源处理器.
initMessageSource();
// 创建事件多播器
initApplicationEventMulticaster();
// 这个方法同样也是留个子类实现的springboot也是从这个方法进行启动tomcat的.
onRefresh();
//把我们的事件监听器注册到多播器上
registerListeners();
// 实例化我们剩余的单实例bean.
finishBeanFactoryInitialization(beanFactory);
// 最后容器刷新 发布刷新事件(Spring cloud也是从这里启动的)
finishRefresh();
}
catch (BeansException ex) {
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
}
}
}
1,prepareRefresh方法
首先第一步是进入这个prepareRefresh预准备刷新的方法,对一些基础属性进行设置和初始化,其流程如下:
- 首先第一步是设置一些状态,如设置close状态,active状态等
- 第二步是这个 initPropertySources 方法,该方法是给子类去使用的,比如在springmvc中,就实现了这个方法,该方法位于 AbstractRefreshableWebApplicationContext 类中,这样springmvc就可以去xml中的获取配置环境以及系统参数了。该方法底层使用了模板方法模式
- 第三步就是通过这个validateRequiredProperties方法用于验证环境中是否有某些属性,用来校验我们容器启动必须依赖的环境变量的值
- 最后一步就是初始化一些监听器,以及一些早期的事件等
protected void prepareRefresh() {
this.closed.set(false);
this.active.set(true);
initPropertySources();
getEnvironment().validateRequiredProperties();
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
this.earlyApplicationEvents = new LinkedHashSet<>();
}
2,obtainFreshBeanFactory方法
obtainFreshBeanFactory方法的实现如下,其主要目的就是判断是否需要刷新这个beanFactory,以及最终返回一个 BeanFactory
刷新refreshBeanFactory的具体实现类有以下两种,一种是常规的上下文的实现类,一种是可以刷新的上下文实现类
两种底层实现不一致,如果是常规的 GenericApplicationContext 实现类,如果判断这个beanFactory已经加载,那么就是会直接抛异常,但是beanFactory在ApplicationContext初始化的时候就已经初始化beanfactory,因此这个实现类是不允许多次refresh的
如果是 AbstractRefreshableApplicationContext 实现类的话,那么底层就是允许多次refresh刷新的,就是在刷新前会将原来已有的beanFactory给销毁以及关闭,然后重新创建BeanFactory,以及加载refresh之前需要加载的一些BeanDefinition。如springmvc中,那么肯定是需要进行多次刷新的,那么就会实现这个类。
3,prepareBeanFactory方法
在第二步返回了一个beanFactory,那么第三步开始就是对这个bean工厂进行属性填充,那么就直接进入这个prepareBeanFactory方法流程
- 这里首先做的就是设置BeanFactory的类加载器,此时为application应用类加载器;
- 第二步就是设置BeanFactory就是设置一些spel表达式,如@Value注解中的表达式等
- 第三步就是设置一个propertityEditor属性资源编辑器对,比如一些inputStream流等
- 最后就是添加一个bean工厂的后置处理器,用于在处理ApplicationContextAware接口回调
//设置bean工厂的类加载器为当前application应用的加载器
beanFactory.setBeanClassLoader(getClassLoader());
//为bean工厂设置我们标准的SPEL表达式解析器对象StandardBeanExpressionResolver
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//为我们的bean工厂设置了一个propertityEditor 属性资源编辑器对象(用于后面的给bean对象赋值使用)
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
//注册了一个完整的ApplicationContextAwareProcessor 后置处理器用来处理ApplicationContextAware接口的回调方法
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
设置完以上的基础属性之后,前期会对一些aware进行一些忽略,如EnvironmentAware 方法等
随后就是注册一些解析依赖,就是一些map映射关系,比如BeanFactory类对应的依赖就是BeanFactory
随后就是在bean的后置处理器中,增加一个监听探测器
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工厂中是否包含一些系统环境,系统属性等,如果不存在,那么就会手动的注册一个
4,postProcessBeanFactory方法
接下来就是进入第4个方法postProcessBeanFactory,顾名思义,就是BeanFactory的后置处理器,用于内部子类的一些扩展,和postProcessBean需要区分,一个是给BeanFactory用的,一个是给Bean用的。
postProcessBeanFactory方法如下,内部是一个空方法,主要是提供给子类去实现。其实现类如下,主要有4个核心的实现类,但是这几个实现类主要是跟web相关,如在springmvc中使用
来分析一个具体实现,如 AbstractRefreshableWebApplicationContext 类中具体实现,首先会提前增加一个servletContext相关的后置处理器,然后忽略一些Aware回调接口,最后去注册一些web的作用域,环境变量bean等
除了上面这个实现类之外,其他的一些实现类也是基于web这一块去实现的,更多的还是作用与springmvc以及springboot中,是这些组件中的一些扩展
5,invokeBeanFactoryPostProcessors方法
接下来来到第五个方法 invokeBeanFactoryPostProcessors ,也是在refresh中比较重要,内容比较多的一个方法。其底层实现主要如下,内部主要是通过这个PostProcessorRegistrationDelegate类调用实现
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
首先第一步就是判断bean工厂是否是BeanDefinitionRegistry的子实现类,是的话那么就会循环外部子类所注册的BeanFactoryPostProcessor,然后将这些postProcessor强制转换成BeanDefinitionRegistryPostProcessor,然后加入到list集合中
下面这段代码是接着上面的代码,先去容器中获取BeanDefinitionRegistryPostProcessor的bean的处理器名称,随后通过这些名称进行匹配,判断是否实现了 PriorityOrdered 优先级接口,随后通过这个sortPostProcessors方法进行排序,随后通过这个invokeBeanDefinitionRegistryPostProcessors方法进行bean定义的加载,比如一些@Import等等,最后进行排序和注册功能
依旧是接着上面的代码,依旧是去容器中获取BeanDefinitionRegistryPostProcessor的bean的处理器名称,然后这里实现的是判断是否实现了 @Ordered 接口,然后完成排序注册等
还是接着上面的这段代码,上面两段代码是处理带有优先级的,接下来的这段代码就是处理没有实现任何优先级的BeanDefinitionRegistryPostProcessor,然后进行排序,注册到registryProcessors里面
处理完以上的操作之外,最后进行bean工厂的后置处理器的操作,将上面的优先级进行BeanFactory后置处理器的实现,依次先执行 priorityOrdered 实现类,Ordered 实现类,最后就是没有实现优先级接口的实现类
//获取容器中所有的 BeanFactoryPostProcessor
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
//保存BeanFactoryPostProcessor类型实现了priorityOrdered
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
//保存BeanFactoryPostProcessor类型实现了Ordered接口的
List<String> orderedPostProcessorNames = new ArrayList<>();
//保存BeanFactoryPostProcessor没有实现任何优先级接口的
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
//processedBeans包含的话,表示在上面处理BeanDefinitionRegistryPostProcessor的时候处理过了
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
//判断是否实现了PriorityOrdered 优先级最高
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
//判断是否实现了Ordered 优先级 其次
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
//没有实现任何的优先级接口的 最后调用
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 先调用BeanFactoryPostProcessor实现了 PriorityOrdered接口的
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
//再调用BeanFactoryPostProcessor实现了 Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
//调用没有实现任何方法接口的
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
因此这个方法主要有两个作用,一个是完成所有bean的扫描,一个是完成BeanFactory的后置处理器的调用
6,registerBeanPostProcessors方法
接下来第六个方法registerBeanPostProcessors注册bean的后置处理器,在第五个方法中,完成了bean工厂的后支持处理器,接下来看一下内部是如何实现的
在这个方法中,首先第一步还是在bean工厂获取全部的bean的名称
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
在这个bean的后置处理器中,和扫描bean工厂的后后置处理器的方式一样,先过滤实现 priorityOrdered 注解的的bean,然后过滤出实现Ordered注解的bean,最后扫描没有任何优先级的bean
随后对priorityOrdered注解的bean进行排序和注册,最后加入到BeanFactory容器中
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
随后对ordered注解的bean进行排序和注册,最后加入到BeanFactory容器中
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
随后注册没有实现任何排序接口的的bean,加入到BeanFactory容器
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
随后注册MergedBeanDefinitionPostProcessor类型的bean,加入到BeanFactory容器
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
最后注册ApplicationListenerDetector监听器类型的bean,加入到BeanFactory容器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
5完成的是beanFactory的后置处理器的扫描和注册,6完成的就是bean后置处理器的扫描和注册
7,initMessageSource方法
接下来查看这个 initMessageSource 方法,顾名思义,这个方法就是用来国际化资源的一个方法。主要是创建一些 MessageSource 的类,或者获取到xml文件中的MessageSource,最后将这个实例加入到 beanFactory中
protected void initMessageSource() {
//获取Bean工厂,一般是DefaultListBeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//首先判断是否已有xml文件定义了id为messageSource的bean对象
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
//如果有,则从Bean工厂得到这个bean对象
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
//当父类Bean工厂不为空,并且这个bean对象是HierarchicalMessageSource类型
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
//为HierarchicalMessageSource的实现类
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
//设置父类MessageSource,此处设置内部的parent messageSource
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
DelegatingMessageSource dms = new DelegatingMessageSource();
//给这个DelegatingMessageSource添加父类消息源
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
//将这个messageSource实例注册到Bean工厂中
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
8,initApplicationEventMulticaster方法
顾名思义就是初始化一个事件发布器的方法,就是先判断这个事件发布器有没有定义,如果有定义就直接用已经定义的方法,如果没有定义那么就会new一个默认事件发布器,然后注册到容器里面
9,onrefresh方法
接下来继续看这个onrefresh方法,其主方法为空,也就是主要是交给子类去实现,和上面的postProcessBeanFactory 方法一样,并且通过具体的实现类发现,这些实现类主要也是和web那一块相关,也就是跟springmvc和springboot那块有关
10,registerListeners方法
在第八个方法中,已经完成了事件发布器的初始化以及获取,这一块逻辑也比较简单,就是判断开发者有没有自定义一些事件监听器,有的话将全部的事件监听器加入到事件发布器里面
11,finishBeanFactoryInitialization方法
在第一篇spring的bean的什么周期中,就是通过这个方法进入的,就是实例化一些非类加载的单例bean,方法内部会调用一个 preInstantiateSingletons 用于真正的实例化剩余的单例bean,内部就会经过一些bean的实例化、属性填充、初始化等方法,以及一些bean的后置处理器的实现,aop的初始扫描,@Autowire等注解的预卖点,aop最终产生动态代理等,底层详细的可以参考这个系列的第一篇方法
之前画的bean的生命周期的图片,就是通过这个方法进入的,在调用getbean的流程到bean加入到concurrentHashMap的流程都在这里面实现
12,finishRefresh方法
在最后的refresh方法中,最后要执行的就是这个 finishRefresh ,其主要流程如下:
- 首先第一步就是清除上下文级别的资源缓存,比如扫描出来的一些ASM元数据
- 注册lifecycleProcessor,它会通过LifecycleProcessor来与所有声明的bean的周期做状态更新
- getLifecycleProcessor(),实现SmartLifecycle并且isAutoStartup自动启动的Lifecycle调用start()方法
- 随后会注册一个发布事件的容器,将那些事件发布器和事件监听器全部注册
## 12,finishRefresh方法
在最后的refresh方法中,最后要执行的就是这个 finishRefresh ,其主要流程如下:
- 首先第一步就是清除上下文级别的资源缓存,比如扫描出来的一些ASM元数据
- 注册lifecycleProcessor,它会通过LifecycleProcessor来与所有声明的bean的周期做状态更新
- getLifecycleProcessor(),实现SmartLifecycle并且isAutoStartup自动启动的Lifecycle调用start()方法
- 随后会注册一个发布事件的容器,将那些事件发布器和事件监听器全部注册