Spring源码之九finishRefresh详解

贵有恒,何必三更起、五更眠、最无益,只怕一日曝、十日寒。这篇文章主要讲述Spring源码之九finishRefresh详解相关的知识,希望能为你提供帮助。
Spring源码之九finishRefresh详解
Spring IoC 的核心内容要收尾了,本文将对最后一个方法 finishRefresh 进行介绍,位于refresh 方法中的第九个位置。
本章实际是对发布订阅模式的一种补充,这是Spring在刷新事件完成后发布事件。
由于存在上下文关系,本文也会对 initApplicationEventMulticaster 方法、registerListeners 方法进行回顾。
我们回到refresh 方法中。

@Override public void refresh() throws BeansException, IllegalStateException synchronized (this.startupShutdownMonitor) // Prepare this context for refreshing. //1、刷新前的准备 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //2、将会初始化 BeanFactory、加载 Bean、注册 Bean ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //3、设置 BeanFactory 的类加载器,添加几个 BeanPostProcessor,手动注册几个特殊的 bean prepareBeanFactory(beanFactory); try //4、模板方法 // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //执行BeanFactory后置处理器 invokeBeanFactoryPostProcessors(beanFactory); // 5、Register bean processors that intercept bean creation. //注册bean后置处理器 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //国际化 initMessageSource(); // Initialize event multicaster for this context. //初始化事件广播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //6、模板方法--springboot实现了这个方法 onRefresh(); // Check for listener beans and register them. //7、注册监听器 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //8、完成bean工厂的初始化**方法重要********************************************** finishBeanFactoryInitialization(beanFactory); //9、 Last step: publish corresponding event. //完成上下文的刷新工作 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 Springs core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches();

我们首先知道这个三个方法的作用:
initApplicationEventMulticaster():初始化应用的事件广播器
/** * Initialize the ApplicationEventMulticaster. * Uses SimpleApplicationEventMulticaster if none defined in the context. * @see org.springframework.context.event.SimpleApplicationEventMulticaster */ protected void initApplicationEventMulticaster() ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 1.判断BeanFactory是否已经存在事件广播器(固定使用beanName=applicationEventMulticaster) if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) // 1.1 如果已经存在,则将该bean赋值给applicationEventMulticaster this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isTraceEnabled()) logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); else // 1.2 如果不存在,则使用SimpleApplicationEventMulticaster this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isTraceEnabled()) logger.trace("No " + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + " bean, using " + "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");

最终只做了一件事,初始化应用的事件广播器。(具体什么是事件广播器及其作用可见上上篇文章,具体就不在吃赘述了)
registerListeners():注册监听器。见上上篇文章
finishRefresh():完成上下文的刷新工作,本文重点。
首先概览finishRefresh方法
protected void finishRefresh() // Clear context-level resource caches (such as ASM metadata from scanning). //清除资源缓存 clearResourceCaches(); // Initialize lifecycle processor for this context. // // 1.为此上下文初始化生命周期处理器 initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. // 2.首先将刷新完毕事件传播到生命周期处理器(触发isAutoStartup方法返回true的SmartLifecycle的start方法) getLifecycleProcessor().onRefresh(); // Publish the final event. // 3.推送上下文刷新完毕事件到相应的监听器 publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this);

1、2、3是重点内容
1.为此上下文初始化生命周期处理器
protected void initLifecycleProcessor() ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 1.判断BeanFactory是否已经存在生命周期处理器(固定使用beanName=lifecycleProcessor) if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class); if (logger.isTraceEnabled()) logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]"); else // 1.2 如果不存在,则使用DefaultLifecycleProcessor DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor(); defaultProcessor.setBeanFactory(beanFactory); this.lifecycleProcessor = defaultProcessor; // 并将DefaultLifecycleProcessor作为默认的生命周期处理器,注册到BeanFactory中 beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor); if (logger.isTraceEnabled()) logger.trace("No " + LIFECYCLE_PROCESSOR_BEAN_NAME + " bean, using " + "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");

【Spring源码之九finishRefresh详解】2.首先将刷新完毕事件传播到生命周期处理器
private void startBeans(boolean autoStartupOnly) // 1.获取所有的Lifecycle bean Map< String, Lifecycle> lifecycleBeans = getLifecycleBeans(); // 将Lifecycle bean 按阶段分组,阶段通过实现Phased接口得到 Map< Integer, LifecycleGroup> phases = new HashMap< > (); // 2.遍历所有Lifecycle bean,按阶段值分组 lifecycleBeans.forEach((beanName, bean) -> // autoStartupOnly=true代表是ApplicationContext刷新时容器自动启动;autoStartupOnly=false代表是通过显示的调用启动 // 3.当autoStartupOnly=false,也就是通过显示的调用启动,会触发全部的Lifecycle; // 当autoStartupOnly=true,也就是ApplicationContext刷新时容器自动启动,只会触发isAutoStartup方法返回true的SmartLifecycleif (!autoStartupOnly || (bean instanceof SmartLifecycle & & ((SmartLifecycle) bean).isAutoStartup())) // 3.1 获取bean的阶段值(如果没有实现Phased接口,则值为0) int phase = getPhase(bean); // 3.2 拿到存放该阶段值的LifecycleGroup LifecycleGroup group = phases.get(phase); if (group == null) // 3.3 如果该阶段值的LifecycleGroup为null,则新建一个 group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly); phases.put(phase, group); // 3.4 将bean添加到该LifecycleGroup group.add(beanName, bean); ); // 4.如果phases不为空 if (!phases.isEmpty()) List< Integer> keys = new ArrayList< > (phases.keySet()); // 4.1 按阶段值进行排序 Collections.sort(keys); // 4.2 按阶段值顺序,调用LifecycleGroup中的所有Lifecycle的start方法 for (Integer key : keys) phases.get(key).start();

3.推送上下文刷新完毕事件到相应的监听器
protected void publishEvent(Object event, @Nullable ResolvableType eventType) Assert.notNull(event, "Event must not be null"); // Decorate event as an ApplicationEvent if necessary // 1.如有必要,将事件装饰为ApplicationEvent ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) applicationEvent = (ApplicationEvent) event; else applicationEvent = new PayloadApplicationEvent< > (this, event); if (eventType == null) eventType = ((PayloadApplicationEvent< ?> ) applicationEvent).getResolvableType(); // Multicast right now if possible - or lazily once the multicaster is initialized if (this.earlyApplicationEvents != null) this.earlyApplicationEvents.add(applicationEvent); else // 2.使用事件广播器广播事件到相应的监听器 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); // Publish event via parent context as well... // 3.同样的,通过parent发布事件..... if (this.parent != null) if (this.parent instanceof AbstractApplicationContext) ((AbstractApplicationContext) this.parent).publishEvent(event, eventType); else this.parent.publishEvent(event);

这里面调用的publishEvent方法,和我们自定义的监听器调用的publishEvent是同一个方法,ContextRefreshedEvent是Spirng的一个事件称为上下文刷新完毕事件,如果我们在上下文刷新完成后要写一个发布事件,实现ApplicationListener< ContextRefreshedEvent> 接口即可。
我们在此举一个简单的例子。
Spring源码之九finishRefresh详解

文章图片

Spring源码之九finishRefresh详解

文章图片

这样,当 Spring 执行到 finishRefresh 方法时,就会将 ContextRefreshedEvent 事件推送到 MyRefreshedListener 中。
读者可以结合自定义事件对比一个和Spring提供的刷新上下文事件的区别,以便于更好的理解Spring的事件监听机制。
跟 ContextRefreshedEvent 相似的还有:ContextStartedEvent、ContextClosedEvent、ContextStoppedEvent。
好啦,Spirng的refresh方法到这里就结束啦,一共是九篇博客,实际上这也是Spirng的IOC的全部内容了,如果读者能把九篇的完全消化,那么spring的IOC也就理解的七七八八了。

    推荐阅读