概要
过度
上面我们宏观介绍了refresh()
的基本思路:
接下来我们按照框出来的四个部分依次介绍,本节介绍的是错误验证及启动事件的广播。
内容简介
通过上面的几步,我们基本把能配置的都配置完了。但是还有一个问题,很多时候我们注册的BD配置是有问题的,比如:
- 配置的属性从环境或者配置文件中去不到
- 依赖不存在
- 有多个依赖可用
- 等等。。。。
在工作中经常遇到的是JSF服务不存在,也就是找不到分布式服务的服务提供者。
所以,我们直接把所有的非懒加载的单例都进行实例化,这样如果有什么低级错误,在启动时就报错了,不会等到上线一天之后突然报警。
我们本节介绍的还有一个内容是相关事件的广播,也可以看作是上面各种context
配置的一次使用。
所属环节
错误验证及启动事件的广播。
上下环节
上文: BeanFactory
和ApplicationContext
的配置
下文:启动结束,可以开始服务
源码解析
入口
还是把refresh()
贴出来:
// TODO 模版方法
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 准备此 ApplicationContext
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// BeanFactory 的初始化及对应的 BD 的加载
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 对 BeanFactory 中的一些和上下文相关的属性进行设置和同步。
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
// 定义了一个钩子,供子类实现
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
// 调用 BeanFactory 的后处理器对其进行处理
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 注册那些拦截 Bean 创建的后处理器
// 注意,上面 invokeBeanFactoryPostProcessors() 各种实例化各种注册,操作的都是针对 factory 的后处理器。这里才是针对 bean
// 的后处理器
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
// 初始化本 context 的 Message 源【国际化和本土化】【将对应的信息符号转化成对应的语言提示】
// TODO 没啥需要,最后再看
initMessageSource();
// Initialize event multicaster for this context.
// 初始化事件广播相关的东西
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
// 子实现类根据各自情况实现其他的特殊 Bean 的处理
// 算是留下的一个钩子
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();
}
}
}
��我们关注的是finishBeanFactoryInitialization()
和finishRefresh()
两行代码干的事。
初始化所有单例
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
// 完成 BeanFactory 的初始化
// 完成剩余的非懒加载单例 Bean 的实例化
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 从配置的 value 反序列化:
// 1. 使用我们上面的 PropertyEditorRegistrar 之类的来做
// 2. 使用 converter
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));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// TODO 这个是做什么的?? 在什么时候从 BeanFactory 中拉出来并发挥作用的???
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 一个 aware ,用来获得项目启动时间的,在项目启动时对其进行初始化
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// 不再允许 BD 的修改
// 【可以继续注册新的BD】
// 【不许修改注册的 bd ,但是你自己拉出来的 mbd 还是可以继续用后处理器修改的,改完还能自己缓存】
beanFactory.freezeConfiguration();
// 至此,完成对 BeanFactory 的所有初始化操作
// Instantiate all remaining (non-lazy-init) singletons.
// 将 "完成剩余的非懒加载单例 Bean 的实例化" 工作委托给 BeanFactory
beanFactory.preInstantiateSingletons();
}
我感觉这个函数做的东西有点杂乱:
实例化和注册 ConversionService.class
对ConversionService.class
类型的进行了实例化和注册。它的职能是将指定的配置入参String序列化成对应的类型。和prepareBeanFactory()
中的beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
类似,不过那里只是硬编码添加了对资源加载的解析。
当然,这里是context
增加了对ConversionService
的支持。我们该从哪入手去定制第二种情况的配置呢?通过CustomEditorConfigurer
,这是个BeanFactoryPostProcessor
。言尽于此。
对LoadTimeWeaverAware
对提前实例化
卧槽,这里看不懂,ApplicationContext
虽然增加了对LoadTimeWeaverAware
的支持,但是它已经通过后处理器提供了支持,这里为啥要提前手动加载一次?
初始化非懒加载的单例
委托给了beanFactory.preInstantiateSingletons()
。这里不再细说。
散发初始化完成的事件
这里对应的是refresh()
的finishRefresh();
一句:
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// TODO 这个生命周期控制,还不清楚
// Initialize lifecycle processor for this context.
// LifecycleProcessor ,实现此接口,Spring 框架会在启动时调用它的 start ,结束时调用 stop
// 后台进程的优先选择。。。。。
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// 发布事件
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
做了两件事:
- 增加对生命周期的支持,调用了生命周期的钩子【个人感觉这里有点多余,用事件通知完全能替代这部分功能】
- 发送消息通知——启动完成
网友评论