目录
代码块1:initApplicationEventMulticaster
Spring IoC源码学习全系列
Spring IoC源码学习:ApplicationContext刷新前的配置
Spring IoC源码学习:obtainFreshBeanFactory详解
Spring IoC源码学习:parseDefaultElement详解
Spring IoC源码学习:parseCustomElement详解
Spring IoC源码学习:context:component-scan节点详解
Spring IoC源码学习:invokeBeanFactoryPostProcessors详解
Spring IoC源码学习:registerBeanPostProcessors详解
Spring IoC源码学习:finishBeanFactoryInitialization详解
Spring IoC源码学习:createBean详解(上)
Spring IoC源码学习:createBean详解(下)
Spring IoC源码学习:finishRefresh 详解
Spring IoC 的核心内容已经介绍完毕,本文将对最后一个方法 finishRefresh 进行介绍。由于存在上下文关系,本文也会对 initApplicationEventMulticaster 方法、registerListeners 方法进行介绍。
首先,我们回到 refresh 方法。
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // 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 Spring's core, since we // might not ever need metadata for singleton beans anymore... resetCommonCaches(); } } }
initApplicationEventMulticaster():初始化应用的事件广播器,见代码块1详解。
registerListeners():注册监听器,见代码块2详解。
finishRefresh():完成上下文的刷新工作,见代码块3详解。
代码块1:initApplicationEventMulticaster
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.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { // 1.2 如果不存在,则使用SimpleApplicationEventMulticaster this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); // 并将SimpleApplicationEventMulticaster作为默认的事件广播器,注册到BeanFactory中 beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isDebugEnabled()) { logger.debug("Unable to locate ApplicationEventMulticaster with name '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "': using default [" + this.applicationEventMulticaster + "]"); } } }
内容比较简单,就是要初始化应用的事件广播器。通过之前的学习我们知道,在 Spring 中,有一些内部的 bean 会使用固定的 beanName,这边的事件广播器就是这样,固定使用 beanName :applicationEventMulticaster。
具体的,如果当前 BeanFactory 中已经存在 beanName = applicationEventMulticaster 的 bean 实例或者 BeanDefinition,那么就使用该 bean 作为 applicationEventMulticaster。
否则,新建一个默认的事件广播器 SimpleApplicationEventMulticaster 作为 applicationEventMulticaster,并且会注册到 BeanFactory 中。
protected void registerListeners() { // Register statically specified listeners first. // 1.通过硬编码调用addApplicationListener方法添加的监听器处理(可以通过自定义ApplicationContextInitializer添加) for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! // 2.通过配置文件或注解注入BeanFactory的监听器处理 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // Publish early application events now that we finally have a multicaster... // 3.使用事件广播器,发布早期应用程序事件到相应的监听器 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
1.通过硬编码调用 addApplicationListener 方法添加的监听器处理,可以通过自定义ApplicationContextInitializer 添加,关于自定义 ApplicationContextInitializer 请见Spring IoC:ApplicationContext刷新前的配置中的代码块12。
protected void finishRefresh() { // 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.为此上下文初始化生命周期处理器,见代码块4详解。
2.首先将刷新完毕事件传播到生命周期处理器,见代码块5详解。
3.推送上下文刷新完毕事件到相应的监听器,见代码块6详解。
protected void initLifecycleProcessor() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 1.判断BeanFactory是否已经存在生命周期处理器(固定使用beanName=lifecycleProcessor) if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) { // 1.1 如果已经存在,则将该bean赋值给lifecycleProcessor this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class); if (logger.isDebugEnabled()) { logger.debug("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.isDebugEnabled()) { logger.debug("Unable to locate LifecycleProcessor with name '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "': using default [" + this.lifecycleProcessor + "]"); } } }
初始化生命周期处理器,过程同代码块1类似,优先使用用户自定义的生命周期处理器;如果用户没有自定义,则使用默认的DefaultLifecycleProcessor。
@Override public void onRefresh() { startBeans(true); this.running = true; } private void startBeans(boolean autoStartupOnly) { // 1.获取所有的Lifecycle bean Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); // 将Lifecycle bean 按阶段分组,阶段通过实现Phased接口得到 Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>(); // 2.遍历所有Lifecycle bean,按阶段值分组 for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) { Lifecycle bean = entry.getValue(); // autoStartupOnly=true代表是ApplicationContext刷新时容器自动启动;autoStartupOnly=false代表是通过显示的调用启动 // 3.当autoStartupOnly=false,也就是通过显示的调用启动,会触发全部的Lifecycle; // 当autoStartupOnly=true,也就是ApplicationContext刷新时容器自动启动,只会触发isAutoStartup方法返回true的SmartLifecycle if (!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(entry.getKey(), bean); } } // 4.如果phases不为空 if (!phases.isEmpty()) { List<Integer> keys = new ArrayList<Integer>(phases.keySet()); // 4.1 按阶段值进行排序 Collections.sort(keys); // 4.2 按阶段值顺序,调用LifecycleGroup中的所有Lifecycle的start方法 for (Integer key : keys) { phases.get(key).start(); } } }
这边讲下 autoStartupOnly 这个参数。
autoStartupOnly = true 时,代表这次刷新是 ApplicationContext刷新时容器自动启动,在这个阶段只会触发 SmartLifecycle,并且要求 SmartLifecycle 的isAutoStartup() 方法必须返回 true。
而 autoStartupOnly = false,代表这次刷新是通过显示的调用启动,会触发所有的 Lifecycle。
这边还引入了 Phased 接口,这个接口类似于 Ordered 接口,只有一个方法用于返回一个 “阶段值”,范围为 Integer.MIN_VALUE ~ Integer.MAX_VALUE。在启动过程,“阶段值” 小的会被优先调用,而在关闭过程,“阶段值” 大的会被优先调用。
@Override public void publishEvent(ApplicationEvent event) { publishEvent(event, null); } protected void publishEvent(Object event, ResolvableType eventType) { Assert.notNull(event, "Event must not be null"); if (logger.isTraceEnabled()) { logger.trace("Publishing event in " + getDisplayName() + ": " + event); } // Decorate event as an ApplicationEvent if necessary // 1.如有必要,将事件装饰为ApplicationEvent ApplicationEvent applicationEvent; if (event instanceof ApplicationEvent) { applicationEvent = (ApplicationEvent) event; } else { applicationEvent = new PayloadApplicationEvent<Object>(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); } } }
2.使用事件广播器广播事件到相应的监听器,见代码块7详解。
@Override public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); // 1.getApplicationListeners:返回与给定事件类型匹配的应用监听器集合 for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) { // 2.返回此广播器的当前任务执行程序 Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { // 3.1 executor不为null,则使用executor调用监听器 invokeListener(listener, event); } }); } else { // 3.2 否则,直接调用监听器 invokeListener(listener, event); } } }
3.2 调用监听器,见代码块8详解。
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) { // 1.返回此广播器的当前错误处理程序 ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { // 2.1 如果errorHandler不为null,则使用带错误处理的方式调用给定的监听器 doInvokeListener(listener, event); } catch (Throwable err) { errorHandler.handleError(err); } } else { // 2.2 否则,直接调用调用给定的监听器 doInvokeListener(listener, event); } } private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try { // 触发监听器的onApplicationEvent方法,参数为给定的事件 listener.onApplicationEvent(event); } catch (ClassCastException ex) { String msg = ex.getMessage(); if (msg == null || msg.startsWith(event.getClass().getName())) { // Possibly a lambda-defined listener which we could not resolve the generic event type for Log logger = LogFactory.getLog(getClass()); if (logger.isDebugEnabled()) { logger.debug("Non-matching event type for listener: " + listener, ex); } } else { throw ex; } } }
如果我们想在 Spring IoC 容器构建完毕之后进行一些逻辑,就可以通过监听器来实现。
创建一个自定义监听器,实现 ApplicationListener 接口,监听 ContextRefreshedEvent(上下文刷新完毕事件),并且将该监听器注册到 Spring IoC容器即可。
import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component; /** * @author joonwhee * @date 2019/6/22 */ @Component public class MyRefreshedListener implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent event) { // 自己的逻辑处理 } }
这样,当 Spring 执行到 finishRefresh 方法时,就会将 ContextRefreshedEvent 事件推送到MyRefreshedListener 中。
跟 ContextRefreshedEvent 相似的还有:ContextStartedEvent、ContextClosedEvent、ContextStoppedEvent,有兴趣的可以自己看看这几个事件的使用场景。
当然,我们也可以自定义监听事件,只需要继承 ApplicationContextEvent 抽象类即可。
本文主要介绍了几个用于扩展使用的功能:
· ApplicationEventMulticaster:应用事件广播器,用于发布事件到相应的监听器。
· LifecycleProcessor:生命周期处理器,用于处理生命周期事件。
· Lifecycle:定义生命周期控制方法的接口,特别是 SmartLifecycle,可以
在 Spring IoC 容器刷新完毕时进行触发。
· ApplicationContextEvent:应用事件的基类。
· ApplicationListener,应用事件监听器,用于监听应用事件。