大家好,又见面了,我是你们的朋友全栈君。
我们知道,spring 的启动其实就是容器的启动,而一般情况下,容器指的其实就是上下文 ApplicationContext。
AbstractApplicationContext 作为整个 ApplicationContext 体系中最高级的抽象类,为除了 ComplexWebApplicationContext 和 SimpleWebApplicationContext 这两个容器外的全部容器,规定好了 refresh 的整体流程,所有的容器在完成一些自己的初始化配置后,都需要调用该 refresh 方法,依次完成指定内容的初始化。
也就是说,读懂了 AbstractApplicationContext.refresh() 方法,其实就读懂了容器的启动流程:
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // ================= 一、上下文的初始化 ================= // 准备上下文 prepareRefresh(); // 通知子类刷新内部工厂 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 准备bean工厂以便在当前上下文中使用 prepareBeanFactory(beanFactory); try { // ================= 二、BeanFactory的初始化 ================= // 对工厂进行默认后置处理 postProcessBeanFactory(beanFactory); // 使用后置处理器对工厂进行处理 invokeBeanFactoryPostProcessors(beanFactory); // 注册Bean后置处理器 registerBeanPostProcessors(beanFactory); // ================= 三、事件,Bean及其他配置的初始化 ================= // 初始化此上下文的消息源 initMessageSource(); // 为此上下文初始化事件广播者 initApplicationEventMulticaster(); // 初始化特定上下文子类中的其他特殊bean onRefresh(); // 检查侦听器bean并注册 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(); } } }
从总体来看,该方法描述的初始化过程大概分为三步:
上下文的初始化; BeanFactory 初始化; 事件,Bean及其他配置的初始化;笔者将基于 spring 源码 5.2.x 分支,分别通过五篇文章从源码分析 spring 容器的初始化过程。
本文是其中的第三篇文章,将介绍上下文中事件,Bean及其他配置的初始化。
相关文章:
深入理解Spring容器初始化(一):上下文的初始化;深入理解Spring容器初始化(二):BeanFactory的初始化;深入理解Spring容器初始化(三):事件及其他配置的初始化;调用 AbstarctApplicationContext.initMessageSource() 用于初始化上下文所使用的数据源对象 MessageSource,这个配置用于支持国际化的信息处理,一般情况下比较少会直接去配置它:
protected void initMessageSource() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 如果当前上下文否存在名为“messageSource”的Bean if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // Make MessageSource aware of parent MessageSource. if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { // 若父容器没有MessageSource,就把它设置为父容器的MessageSource HierarchicalMessageSource hms = (HierarchicalMessageSource) this.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 { // 不存在就尝试获取父容器的MessageSource DelegatingMessageSource dms = new DelegatingMessageSource(); dms.setParentMessageSource(getInternalParentMessageSource()); this.messageSource = dms; beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); if (logger.isTraceEnabled()) { logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]"); } } }
调用 AbstarctApplicationContext.initApplicationEventMulticaster() 是初始化 spring 事件机制的第一步,它的作用很简单:
如果当前 BeanFactory 有名为 “applicationEventMulticaster” 的 ApplicationEventMulticaster,就把它设置为当前上下文的事件广播器,否则就创建并在 BeanFactory 中注册一个SimpleApplicationEventMulticaster 实例作为当前上下文的事件广播器。
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 是否存在“applicationEventMulticaster”这个Bean 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 { // 没有就创建一个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() + "]"); } } }
AbstarctApplicationContext.onRefresh() 用于在完成上下文与 BeanFactory 初始化后去初始化一些特殊的 Bean,其实从方法名就可以看出来,这个方法主要是作为上下文初步刷新完毕后的回调使用。
在 AbstarctApplicationContext 中只提供了空实现,实际上也只有很少的实现类会去重新实现这个方法,至少在 5.2.x 里面,关于这个方法的有用实现只有:
UiApplicationContextUtils.initThemeSource(this)
该代码用于初始化一些 spring 的“主题资源”,一般用于配合消息国际化进行一些处理。
当消息和事件相关的内容都准备就绪后,上下文会调用 AbstarctApplicationContext.registerListeners 方法以注册事件监听器 ApplicationListener。
这一步代码不动,实际上逻辑也很简单:
向事件广播器注册已经被注册的上下文中的监听器;向事件广播器注册还没有被实例化的监听器的 BeanName;发布一些早期事件;protected void registerListeners() { // 向事件广播器注册已经被注册的上下文中的监听器 for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // 向事件广播器注册指定的监听器,不过这里只注册BeanName, // 因为有些监听器Bean是由FactoryBean生产的,而在这里FactoryBean实际上还没被生成出来 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // 发布一些早期事件 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (!CollectionUtils.isEmpty(earlyEventsToProcess)) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
这里有两个比较有意思的地方:
getApplicationListeners 获取的监听器实际上也是通过一个名为 EventListenerMethodProcessor 的 BeanFactoryPostProcessor 注册到上下文的;注册 BeanName 而不是直接注册 Bean 这一点是为了迁就 FactoryBean。实际上在初始化 BeanFactory 的时候,调用 BeanFactoryPostProcessor 和注册 BeanPostProcessor 也都专门对此进行了处理;当调用 AbstarctApplicationContext.finishBeanFactoryInitialization() 的时候,spring 会根据 BeanFactory 中已经注册的 BeanDefinition 实例化所有非懒加载的单例 Bean:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 为BeanFactory设置ConversionService // 该接口为spring转换器体系的入口 if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // 注册一个StringValueResolver,没有就从上下文的环境对象中获取 // 该解析器用于解析配置文件中的一些占位符以及SpEL表达式 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // 若存在AOP使用的支持类加载时织入切面逻辑的类加载器,则优先将该Bean初始化 String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // 由于类加载器已经初始化完成,所以可以停用临时的类加载器了 beanFactory.setTempClassLoader(null); // 锁定当前工厂的配置 beanFactory.freezeConfiguration(); // 初始化剩余未初始化的非懒加载单例Bean beanFactory.preInstantiateSingletons(); }
这个方法总共干了五件事:
为 BeanFactory 设置类型转换服务 ConversionService;为 BeanFactory 设置占位符转换器 StringValueResolver;禁用临时的类加载器,若有则启用支持类加载时织入切面逻辑的类加载器;锁定当前 BeanFactory 的配置;初始化剩余未初始化的非懒加载单例 Bean;这里我们重点关注 BeanFactory.preInstantiateSingletons() 方法,此处是实际上完成 Bean 初始化的代码:
public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // 遍历beanName,若BeanName是可以实例化的非懒加载单例Bean,则将其实例化 for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { // 如果是FactoryBean if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; // 类型为SmartFactoryBean,则是否立刻实例化由SmartFactoryBean.isEagerInit()决定 if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged( (PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { // 类型不为SmartFactoryBean,则不立刻实例化 isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { // 实例化bean getBean(beanName); } } } // 获取所有实现了SmartInitializingSingleton接口的Bean,调用Bean初始化后回调afterSingletonsInstantiated for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
这一步主要干了两件事:
如果是允许实例化的非懒加载普通 Bean,就直接初始化;如果是允许实例化的非懒加载 FactoryBean,则判断它是否是 SmartFactoryBean : 如果不是,则放弃直接初始化;如果是,则根据 SmartFactoryBean.isEagerInit() 判断是否要直接初始化;初始化所有可初始化的 Bean 后,如果这些 Bean 实现了 SmartInitializingSingleton 接口,则调用该接口提供的回调函数;这里需要注意两点:
BeanFactory.getBean() 实际才是最终完成 BeanFactory 创建 Bean 实例操作的方法,在这个方法中将根据 BeanDefinition 完成各自依赖的自动装配、Bean 的后置处理等操作,三级缓存也是在这个时候使用的,这部分的内容将会在后续另起一篇文章分析;此处仅预加载了 FactoryBean,而没有懒加载 FactoryBean 里面的 Bean,因此 FactoryBean 提供的 Bean 总是懒加载的;SmartInitializingSingleton 接口用于提供 BeanFactory 在初始化全部非懒加载 Bean 时调用的回调函数;至此,BeanFactory 中所有可以预先初始化的 Bean 都完成的初始化,我们已经可以通过 BeanFactory 正常的去获取 Bean 了。
AbstractApplicationContext.finishRefresh() 是完成容器刷新的最后一步,它跟 AbstractApplicationContext.onRefresh() 一样是一个钩子方法。
protected void finishRefresh() { // 清空资源缓存 clearResourceCaches(); // 初始化上下文的生命周期处理器 initLifecycleProcessor(); // 调用上下文的生命周期处理器 getLifecycleProcessor().onRefresh(); // 发布上下文刷新完毕事件 publishEvent(new ContextRefreshedEvent(this)); // 注册用于支持通过JMX管理spring的组件,这里不过多分析, // 关于JMX具体可以参考这篇文章:http://218.206.242.148:12345/images/20_tencent/20220924/qvgisdwmlpm.html LiveBeansView.registerApplicationContext(this); }
public void clearResourceCaches() { this.resourceCaches.clear(); }
protected void initLifecycleProcessor() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 若存在名为“lifecycleProcessor”的bean,则设置为生命周期处理器 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 + "]"); } } // 若不存在名为“lifecycleProcessor”的bean,则创建一个DefaultLifecycleProcessor并设置为生命周期处理器 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() + "]"); } } }
这里需要着重研究一下生命周期处理器的调用。
在 getLifecycleProcessor().onRefresh() 这一步,将会获取上一步设置到上下文中的 LifecycleProcessor 然后调用:
// AbstraceApplicationContext.getLifecycleProcessor() LifecycleProcessor getLifecycleProcessor() throws IllegalStateException { if (this.lifecycleProcessor == null) { throw new IllegalStateException("LifecycleProcessor not initialized - " + "call 'refresh' before invoking lifecycle methods via the context: " + this); } return this.lifecycleProcessor; }
这里我们以默认的生命周期处理器 DefaultLifecycleProcessor 为例:
@Override public void onRefresh() { startBeans(true); this.running = true; } private void startBeans(boolean autoStartupOnly) { // 获取所有实现了Lifecycle接口的Bean,并按阶段分组装到不同的LifecycleGroup里 Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans(); Map<Integer, LifecycleGroup> phases = new HashMap<>(); lifecycleBeans.forEach((beanName, bean) -> { // 同时满足下述条件的Bean不会被处理 // 1.入参的autoStartupOnly为true // 2.bean实现了SmartLifecycle接口 // 3.SmartLifecycle.isAutoStartup()方法返回false if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) { // 若实现了SmartLifecycle接口,则返回SmartLifecycle.getPhase(),否则默认返回0 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(); } } }
可以看到,这里针对 SmartLifecycle 接口的实现类做了很多特殊化的处理,默认情况下:
实现了 SmartLifecycle 接口的 Bean,需要保证 SmartLifecycle.isAutoStartup 返回 true 才会被处理;没实现 SmartLifecycle 接口,但是实现了 Lifecycle 接口的 Bean 会被直接处理;并且,在处理 Bean 的时候,还会根据声明周期“阶段”按顺序从小到大排序:
实现了 SmartLifecycle 接口的 Bean,按照 SmartLifecycle.getPhase 返回值排序从小到大执行;没实现 SmartLifecycle 接口,但是实现了 Lifecycle 接口的 Bean ,“阶段”视为 0,会被最先处理;这个操作其实也很简单,其实就是调用时间广播器推送一个 ContextRefreshedEvent 事件:
public class ContextRefreshedEvent extends ApplicationContextEvent { public ContextRefreshedEvent(ApplicationContext source) { super(source); } }
这个事件里唯一一个参数就是上下文本身。
这一部分主要逻辑在事件推送上,后续会在专门的文章分析 spring 提供的事件机制,这里就不过多展开。
本文内容比较零散,主要干三件事:
初始化消息源相关组件: initMessageSource:初始化上下文使用的消息源;onRefresh:上下文刷新时的回调函数,但是一般只用于加载 ThemeSource;初始化事件相关组件: initApplicationEventMulticaster:初始化事件广播器;registerListeners:注册容器中的事件监听器 ApplicationListener;初始化 BeanFactory 中所有非抽象的非懒加载 Bean;完成刷新: 清空上下文中的资源缓存;初始化并调用 Bean 生命周期处理器;发布上下文刷新时间;注册并初始化用于支持 JMX 的组件;发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/170760.html原文链接:https://javaforall.cn
CleanMyMacX2023下载安装教程V4.11.5版本