从具体实例分析Spring初始化流程
在博客中Spring初识中,我们介绍了Spring进行Bean管理的实例,我们简单回顾一下。在BookService中的代码首先新建ClassPathXmlApplicationContext实例,随后通过该实例的getBean()方法获取对象的实例。本篇博客中,我们直接从ClassPathXmlApplicationContext类入手详解Spring的初识化流程。
##ClassPathXmlApplicationContext类的继承关系
我们在IDEA中通过快捷键”Shift+option+command+U”就能看到类的继承关系图。
我们可以看出来,ClassPathXmlApplicationContext的继承关系为ClassPathXmlApplicationContext<-AbstractApplicationContext<-AbstractRefreshableConfigApplicationContext<-AbstractRefreshableApplicationContext<-AbstractApplicationContext
我们暂且记住这条继承线,后面的文章中能够用到。
##ClassPathXmlApplicationContext初始化流程
在前面的博客中,我们是通过如下的代码创建实例:
ApplicationContext ctx = new ClassPathXmlApplicationContext("IOCBean1.xml");
核心代码:
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
该构造方法调用了同名构造方法:
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
这个方法分为两个核心步骤
1、设置配置文件的位置 2、如果refresh标志设置为true,调用refresh方法。
下面我们重点分析refresh()方法。源代码如下:
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();
}
}
}
总体而言,refresh方法的核心流程如下:
1、prepareRefresh ---准备refresh,设置标志位 2、obtainFreshFactory ---提取bean信息,注册Bean 3、prepareBeanFactory ---设置bean加载器 4、postProcessBeanFactory ---留待子类的自定义实现 5、invokeBeanFactoryPostProcessors ---调用BeanFactoryPostProcess 6、registerBeanPostProcessors ---注册BeanPostProcess实现类 7、initMessageSource ---国际化 8、initApplicationEventMulticaster ---初始化ApplicationContext广播类 9、onRefresh ---钩子方法,子类中进行特殊的Bean 10、registerListeners ---注册监听器 11、finishBeanFactoryInitialization ---初始化所有单例的实例 12、finishRefresh ---初始化完成
这里我们主要看的方法,分别为prepareRefresh,obtainFreshFactory,invokeBeanFactoryPostProcessors,finishBeanFactoryInitialization
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
logger.debug("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
该方法的核心就是设置一些标志位,包括closed以及active,这两个属性都设置为AtomicBoolean。
接下来我们来看obtainFreshFactory方法,其代码如下:
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
这个方法有两个核心流程:
1、refreshBeanFactory 2、返回BeanFactory,类型为ConfigurableListableBeanFactory
对于当前类AbstractApplicationContext,refreshBeanFactory为接口方法,需要依赖子类的实现,我们下渗一层看到AbstractRefreshableApplicationContext类的对应方法
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(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);
}
}
这个方法中,主要的逻辑为:
1、判断是否存在BeanFactory,如果有的话销毁当前的BeanFactory。 2、创建新的 BeanFactory,加载 Bean 定义、注册 Bean 等等。
对于ApplicationContext,虽然他继承了BeanFactory但是并不能理解为其实现类,其内部有一个BeanFactory实例,对于BeanFactory(DefaultListableBeanFactory)的相关操作均委托给这个实例进行,然而为何要初始化这个类的实例呢,我们再一次回到继承图上,这次我们把目光聚焦在BeanFactory上
我们可以看到,BeanFactory的直接接口有三个,分别为ListableBeanFactory,HierarchicalBeanFactory,AutowireCapableBeanFactory,而对于这三个接口,ConfigurableListableBeanFactory则直接继承了这三个接口,对于AutowireCapableBeanFactory有一个直接实现类,AbstractAutowireCapableBeanFactory。然而这个实现类并不具有ConfigurableListableBeanFactory的属性。而DefaultListableBeanFactory既直接实现了ConfigurableListableBeanFactory,同时实现了ConfigurableListableBeanFactory,具有了上述BeanFactory的所有属性,因此ApplicationContext选择了使用这个类的实例来进行BeanFactory的相关操作。
这篇文章先讲到这里,下一篇中将详细介绍BeanFactory的一个核心数据结构BeanDefination,然后将继续介绍Spring的初始化流程以及Bean的创建流程。
谢谢你请我吃糖果