大家好,我是程序员田同学
上篇文章对spring外围启动办法refresh做了整体的解读,然而只是泛泛而谈,接下来会出一零碎文章对每个办法的源码进行粗浅解读。
第一篇文章见 spring源码之办法概览
首先,第一个办法是prepareRefresh()办法,这个办法做的事很简略,也不是本文的重点。该办法记录容器的启动工夫,初始化监听容器。
protected void prepareRefresh() {
// Switch to active
//纪录启动工夫
this.startupDate = System.currentTimeMillis();
System.out.println("spring启动工夫为--------------------" + this.startupDate);
this.closed.set(false);
System.out.println("spring标记为未敞开--------------------" + this.closed);
this.active.set(true);
System.out.println("spring以后激活状态--------------------" + this.active);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
} else {
logger.debug("Refreshing " + getDisplayName());
}
}
// Initialize any placeholder property sources in the context environment.
//空办法
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
//校验 xml配置文件
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
//初始化applicationListeners监听容器
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<> (this.applicationListeners);
} else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
读者大抵搂一眼即可,对这个办法整体就能很快把握。
接下来才是明天的重头戏——obtainFreshBeanFactory()办法,是refresh()办法中的第二个办法,也是整个refresh()办法中外围办法之一。
该办法次要的作用是,这里将会初始化 BeanFactory、加载 Bean、注册 Bean 等等。(Bean 并没有实现初始化)
点进去obtainFreshBeanFactory()办法咱们一探到底。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 敞开旧的 BeanFactory (如果有),创立新的 BeanFactory,加载 Bean 定义、注册 Bean 等等
refreshBeanFactory();
// 返回刚刚创立的 BeanFactory
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
refreshBeanFactory()应该是这个办法的重头戏,咱们再深刻进去。
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果 ApplicationContext 中曾经加载过 BeanFactory 了,销毁所有 Bean,敞开 BeanFactory
// 留神,利用中 BeanFactory 原本就是能够多个的,这里可不是说利用全局是否有 BeanFactory,而是以后ApplicationContext 是否有 BeanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 初始化一个 DefaultListableBeanFactory,为什么应用这个BeanFactory?因为这是最牛的 BeanFactory。
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 用于 BeanFactory 的序列化
beanFactory.setSerializationId(getId());
// 设置 BeanFactory 的两个配置属性:是否容许 Bean 笼罩、是否容许循环援用
customizeBeanFactory(beanFactory);
// 加载 Bean 到 BeanFactory 中
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
简略提一句,DefaultListableBeanFactory为什么是最牛的BeanFactory看下这个继承图大略就明了。
// 设置 BeanFactory 的两个配置属性:是否容许 Bean 笼罩、是否容许循环援用
customizeBeanFactory(beanFactory);
这个形式只是一个设置,设置是否容许循环依赖,至于什么是循环依赖呢?也就是 A-B-C之间他们相互依赖,spring有一套本人的机制去解决循环依赖,当前文章为进行剖析,这一步仅仅是配置是否容许循环依赖,读者分明就能够了。
// 这个办法将依据配置,加载各个 Bean,而后放到 BeanFactory 中
loadBeanDefinitions(beanFactory);
通过下面一系列的步骤,一个beandefintion就造成,beandefintion就是咱们常说的bean,也就是一个对象的加强版。
接下来就须要把这个bean退出到beanfactory中了,这一步交给loadBeanDefinitions()办法去执行。
spring办法命名的确精妙,只看看办法名大略也晓得每个办法干了什么!
创立一个beanDefinitionReader(bean阅读器)去读取xml中的bean,尽管xml很少用了,然而用它来举例还是很经典的。
真正干活的是loadBeanDefinitions(beanDefinitionReader),往下走很漫长漫长,把咱们xml中的bean解析成BeanDefinition,并调用registerBeanDefinition()办法把它注册到注册核心,发送注册事件。
总结一下,到这里曾经初始化了 Bean 容器,<bean />
配置也相应的转换为了一个个 BeanDefinition,而后注册了各个 BeanDefinition 到注册核心,并且发送了注册事件。
到此obtainFreshBeanFactory() 办法也就正式完结了。
spring的调用过程链路十分十分的长,一步步点进去没一会你就迷了,田同学认为比拟好的一个方法就是,先站在办法体外看这个办法干了什么,而后逐渐拆分进入到每一个办法中。
站在refresh()外看这两个办法,prepareRefresh()筹备一下刷新要做的事,obtainFreshBeanFactory()注册好bean并退出到beanfactory中。
好啦,明天的spring源码剖析就到这里了。
发表回复