Spring Bean的生命周期往深入去看,不是简单的几句话能讲完,早就想写相关的内容,但一直觉得工作量不会低,就没有动笔写。拆成几篇来写,这样也不好给自己太大的压力。
image.png
主要分析,Spring容器的初始化过程,然后如何获取Bean,到最终销毁Bean整个过程经历了什么东西。
代码
主要为了分析,更多的是深入源代码中,代码写的就简单一些
//SpringApp.java文件public class SpringApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
HelloWorld hello = (HelloWorld) applicationContext.getBean("hello");
hello.sayHello();
applicationContext.close();
}
}//HelloWorld 文件public class HelloWorld {
public void sayHello(){
System.out.println("hello World");
}
}//app.xml文件<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="me.aihe.HelloWorld">
</bean>
</beans>文件结构就是这个简单,如下
image.png
过程分析
新建ClassPathXmlApplicationContext实例的时候,最终实例化的构造方法如下
configLocations配置文件位置,支持字符串数组
refresh是否自动的刷新上下文,否则在配置之后要手动的调用refresh方法
parent 父级的上下文
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException { super(parent);
setConfigLocations(configLocations); if (refresh) {
refresh();
}
}其最终的实例化的父类为:
//创建AbstractApplicationContext
public AbstractApplicationContext() { this.resourcePatternResolver = getResourcePatternResolver();
} public AbstractApplicationContext(ApplicationContext parent) { this();
setParent(parent);
}
protected ResourcePatternResolver getResourcePatternResolver() { return new PathMatchingResourcePatternResolver(this);
}设置配置文件的位置,
setConfigLocation(String location)
//支持可变参数,如果locations不存在,那么默认为null
public void setConfigLocations(String... locations) { if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null"); this.configLocations = new String[locations.length]; //处理配置文件的位置,稍作处理
for (int i = 0; i < locations.length; i++) { this.configLocations[i] = resolvePath(locations[i]).trim();
}
} else { this.configLocations = null;
}
}刷新Context, 调用refresh()方法,这里先贴出来整个方法, Refreash方法是容器中非常重要的一个方法,一时间这里不好完全讲说明白,先把每个方法的用途注释写上,接下来我们再一起看看其内部是怎么回事
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 准备刷新的Context.
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
// 告诉子类刷新内部的Bean Factory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
// 准备好Context使用的Bean Factory
prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses.
// 设置Bean的 postPorcess
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
// 调用BeanFactory的 postProcess
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
// 注册Bean的PostProcess
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
//对上下文中的消息源进行初始化
initMessageSource(); // Initialize event multicaster for this context.
//初始化上下文的事件机制
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
//初始化其它特殊的beans
onRefresh(); // Check for listener beans and register them.
//检查这些Bean,并且向容器注册
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
//实例化所有的非懒加载的 Singleton
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.
// 销毁已经创建的singletons避免对资源产生不好的影响
destroyBeans(); // Reset 'active' flag.
//重置 active 标志
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...
//重置所有的caches
resetCommonCaches();
}
}
}涉及到类
PathMatchingResourcePatternResolver
StandardEnvironment
TODO
AbstractRefreshableConfigApplicationContext.resolvePath,其中涉及到了Environment.resolveRequiredPlaceholders(String path)
最后
读代码,如果条理清晰,是一件比较爽的工作,尽量不要急功近利,我们一步一步来,压力都会比较小一点。
作者:Real_man
链接:https://www.jianshu.com/p/2ce01125564f