Spring源码之九finishRefresh详解
公众号搜索【程序员田同学】,专职程序员兼业余写手,生活不止于写代码
Spring源码之一源码环境构建
Spring源码之二refresh()方法概览
Spring源码之三obtainFreshBeanFactory()方法
Spring源码之四prepareBeanFactory()方法
Spring源码之五BeanFactoryPostProcessor(后置处理器)
Spring源码之六-onRefresh()方法
Spring源码之七registerListeners()及发布订阅模式
Spring源码之八finishBeanFactoryInitialization方法即初始化单例bean
Spring IoC 的核心内容要收尾了,本文将对最后一个方法 finishRefresh 进行介绍,位于refresh 方法中的第九个位置。
本章实际是对发布订阅模式的一种补充,这是Spring在刷新事件完成后发布事件。
由于存在上下文关系,本文也会对 initApplicationEventMulticaster 方法、registerListeners 方法进行回顾。
我们回到refresh 方法中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh() ; ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory() ; prepareBeanFactory(beanFactory ) ; try { postProcessBeanFactory(beanFactory ) ; invokeBeanFactoryPostProcessors(beanFactory ) ; registerBeanPostProcessors(beanFactory ) ; initMessageSource() ; initApplicationEventMulticaster() ; onRefresh() ; registerListeners() ; finishBeanFactoryInitialization(beanFactory ) ; finishRefresh() ; } catch (BeansException ex) { if (logger.isWarnEnabled() ) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans() ; cancelRefresh(ex ) ; throw ex; } finally { resetCommonCaches() ; } } }
我们首先知道这个三个方法的作用:
initApplicationEventMulticaster():初始化应用的事件广播器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory() ; if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME) ) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class ) ; if (logger.isTraceEnabled() ) { logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]" ); } } else { 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方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 protected void finishRefresh () { clearResourceCaches (); initLifecycleProcessor (); getLifecycleProcessor ().onRefresh (); publishEvent (new ContextRefreshedEvent(this)); LiveBeansView.registerApplicationContext (this); }
1、2、3是重点内容
1.为此上下文初始化生命周期处理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 protected void initLifecycleProcessor() { ConfigurableListableBeanFactory beanFactory = getBeanFactory() ; 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 { DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor() ; defaultProcessor.setBeanFactory(beanFactory ) ; this.lifecycleProcessor = defaultProcessor; beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this .lifecycleProcessor ) ; if (logger.isTraceEnabled() ) { logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " + "[" + this.lifecycleProcessor.getClass() .getSimpleName() + "]" ); } } }
2.首先将刷新完毕事件传播到生命周期处理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 private void startBeans(boolean autoStartupOnly ) { Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans() ; Map<Integer, LifecycleGroup> phases = new HashMap<>() ; lifecycleBeans.for Each((beanName , bean ) -> { if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup() )) { int phase = getPhase(bean ) ; LifecycleGroup group = phases.get(phase); if (group == null) { group = new LifecycleGroup(phase , this .timeoutPerShutdownPhase , lifecycleBeans , autoStartupOnly ) ; phases.put(phase, group); } group.add(beanName, bean); } }); if (!phases.isEmpty() ) { List<Integer> keys = new ArrayList<>(phases.keySet() ); Collections . sort(keys); for (Integer key : keys) { phases.get(key).start() ; } } }
3.推送上下文刷新完毕事件到相应的监听器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 protected void publishEvent (Object event , @Nullable ResolvableType eventType ) { Assert.notNull(event , "Event must not be null" ); ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event ; } else { applicationEvent = new PayloadApplicationEvent<>(this , event ); if (eventType == null ) { eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType(); } } if (this .earlyApplicationEvents != null ) { this .earlyApplicationEvents.add (applicationEvent); } else { getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); } 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接口即可。
我们在此举一个简单的例子。
这样,当 Spring 执行到 finishRefresh 方法时,就会将 ContextRefreshedEvent 事件推送到 MyRefreshedListener 中。
读者可以结合自定义事件对比一个和Spring提供的刷新上下文事件的区别,以便于更好的理解Spring的事件监听机制。
跟 ContextRefreshedEvent 相似的还有:ContextStartedEvent、ContextClosedEvent、ContextStoppedEvent。
好啦,Spirng的refresh方法到这里就结束啦,一共是九篇博客,实际上这也是Spirng的IOC的全部内容了,如果读者能把九篇的完全消化,那么spring的IOC也就理解的七七八八了。
安利时刻: