Spring的Bean生命周期源码解读
一、什么是Spring Bean的生命周期
对于普通的 Java 对象,当 new 的时候创建对象,然后该对象就能够使用了。一旦该对象不再被使用,则由 Java 自动进行垃圾回收。
而 Spring 中的对象是 bean,bean 和普通的 Java 对象没啥大的区别,只不过 Spring 不再自己去 new 对象了,而是由 IoC 容器去帮助我们实例化对象并且管理它,我们需要哪个对象,去问 IoC 容器要即可。IoC 其实就是解决对象之间的耦合问题,Spring Bean 的生命周期完全由容器控制。
二、Bean的生命周期
1、bean定义:就是从xml或者yaml中读取bean的元信息并定义成beanDefination对象
2、bean注册:将beanDefination对象按照相应的规则注册到缓存池Map中
3、实例化:把beanDefination对象实例化成真正的bean,即调用构造函数
4、依赖注入:调用setter方法,注入属性(自定义属性和容器属性)
5、初始化:用户自定义扩展阶段
6、销毁:销毁是用户能自定义扩展的阶段
三、Spring源码分析解读
spring配置文件加载(xml方式)
ApplicationContext ac = new ClassPathXmlApplicationContext("application-context.xml");
spring加载xml入口ClassPathXmlApplicationContext,点击进入内部查看
// 这是ClassPathXmlApplicationContext的构造函数
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent); // 调用父级构造方法
setConfigLocations(configLocations); // 设置要读取的配置文件路径
if (refresh) { // 是否自动上下文刷新
refresh(); // 调用上下文刷新方法
}
}
// 调用AbstractRefreshableConfigApplicationContext中的setConfigLocations方法
// 这个方法的作用:解析指定的数组路径,如果数组中包含特殊符号,如${var},那么在resolvePath方法中会搜寻匹配的系统变量并替换
public void setConfigLocations(@Nullable 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;
}
}
点击refresh(),进入到AbstractApplicationContext类中
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//1.调用容器准备刷新的方法,获取容器的当前时间,同时给容器设置同步标识
prepareRefresh();
//2.创建新的bean工厂,加载配置;
//告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//3.为BeanFactory配置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
//4.允许在子类上下文对bean工厂进行后处理(为容器的某些子类指定特殊的BeanPost事件处理器)
postProcessBeanFactory(beanFactory);
//5.激活各种BeanFactory处理器;
invokeBeanFactoryPostProcessors(beanFactory);
//6.注册拦截bean创建的bean处理器,这里只是注册,真正的调用是在getBean时候
registerBeanPostProcessors(beanFactory);
//7.初始化信息源,和国际化相关.
initMessageSource();
//8.初始化此上下文的事件多播器
initApplicationEventMulticaster();
//9.模板方法,它可以被覆盖以添加特定于上下文的刷新工作。
onRefresh();
//10.注册监听器
registerListeners();
//11.实例化所有剩余的(非lazy-init)单例,实例化对象
finishBeanFactoryInitialization(beanFactory);
// 12.清除缓存的资源信息,初始化一些声明周期相关的bean,并且发布Context已被初始化的事件
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();
}
}
}
上面的代码实现的功能:
1.Spring容器的创建和配置文件的加载、解析功能;
2.初始化Spring容器相关配置;
3.实例化所有剩余的(非lazy-init)单例;
这里具体来看一下这些方法的作用:
1.prepareRefresh()方法:准备刷新上下文环境
protected void prepareRefresh() {
// 获取当前时间
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}
// 初始化上下文环境中的任何占位符属性源(留给子类实现)
initPropertySources();
// 验证需要的属性文件是否都已经放入环境中
getEnvironment().validateRequiredProperties();
// 存储预刷新状态的ApplicationListeners
// 若雨刷in状态的ApplicationListeners为空,则将ApplicationListeners放入到预刷新状态的ApplicationListeners中
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// 将ApplicationListeners重置为预刷新状态
//若预刷新状态的ApplicationListeners不为空,则将applicationListeners清空,将预刷新状态的ApplicationListeners(earlyApplicationListeners)放入到ApplicationListeners中
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
//创建ApplicationEvents集合,一旦多播器可用,将被发布
this.earlyApplicationEvents = new LinkedHashSet<>();
}
initPropertySources()这个方法点开发现是空的,这里可以理解为Spring框架为用户提供的扩展点,这里留一个空方法留给用户实现,给用户最大扩展Spring的能力。用户可以根据自身的需要重写initPropertySources方法,并在方法中进行个性化的属性处理及设置。
2.obtainFreshBeanFactory();bean工厂的创建和xml等配置文件的加载。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 这里使用了委派设计模式,父类定义了抽象的refreshBeanFactory()方法
// 具体实现调用子类容器的refreshFactory()方法
// 创建新的工厂,如果之前存在,destroyBeans()调用方法销毁;closeBeanFactory()调用方法关闭
// 这里使用到的是AbstractRefreshableApplicationContext子类
// //初始化BeanFactory,并进行XML文件读取,并将得到的BeanFactory记录在当前实体属性中
refreshBeanFactory();
// //获取上一步中新创建的工厂
return getBeanFactory();
}
// 创建bean工厂,这里是AbstractRefreshableApplicationContext类中的refreshBeanFactory()方法
protected final void refreshBeanFactory() throws BeansException {
// 判断beanFactory是否存在
if (hasBeanFactory()) {
// 存在
// 销毁
destroyBeans();
// 关闭
closeBeanFactory();
}
try {
// 这里创建 DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 设置序列化id,若有需要就可根据这个id反序列化到这个beanFactory对象
beanFactory.setSerializationId(getId());
// 对IOC容器进行定制化,比如设置启动参数
customizeBeanFactory(beanFactory);
// 调用载入bean定义的方法,主要这里又使用了一个委派模式
// 在当前类中只定义了抽象的loadBeanDefinitions方法,具体的实现调用子类容器
// 初始化documentReader,并实现对xml的读取和解析
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
// 设置此上下文的bean工厂
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
// 创建一个新的DefaultListableBeanFactory ;getInternalParentBeanFactory()该方法就是获取父级工厂
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}
// 调用的AbstractApplicationContext中的getInternalParentBeanFactory()方法获取父级工厂
// 在AbstractApplicationContext抽象类中
@Nullable
protected BeanFactory getInternalParentBeanFactory() {
return (getParent() instanceof ConfigurableApplicationContext ?
((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent());
}
// 此上下文的父上下文,getParent()获取的就是这个属性,获取父级的上下文
@Nullable
private ApplicationContext parent;
// 来看一下,什么时候设置了父级工厂,这里就要回到ClassPathXmlApplicationContext的构造函数了
// 其中有super(parent);这段代码,作用:调用父级的构造方法,并传递一个参数ApplicationContext parent
// 点击super(parent)
public AbstractXmlApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
// 再次点击super(parent)
public AbstractRefreshableConfigApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
// 再次点击super(parent)
public AbstractRefreshableApplicationContext(@Nullable ApplicationContext parent) {
super(parent);
}
//在AbstractApplicationContext抽象类中看到了setParent(parent);设置父级上下文的方法
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
this();
setParent(parent);
}
// setParent方法如下
public void setParent(@Nullable ApplicationContext parent) {
this.parent = parent;
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment) {
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
}
}
}
//经过上面的源码查看可以看出在实例化ClassPathXmlApplicationContext时设置了父级上下文对象,看参数可知,
//this(new String[] {configLocation}, true, null),此时设置的父级上下文对象为空,即:ApplicationContext parent = null;
//所以这里的getInternalParentBeanFactory方法获取的父级工厂就为null.所以这里创建的DefaultListableBeanFactory传递的父级工厂为null。
// 配置上一步创建的beanFactory
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
// 如果allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性
if (this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// 如果allowCircularReferences不为空,设置给beanFactory对象相应属性
if (this.allowCircularReferences != null) {
// 是否允许bean之间存在循环依赖
beanFactory.setAllowCircularReferences(this.allowCircularReferences);
}
}
// 配置XmlBeanDefinitionReader,读取配置文件
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 为指定的beanFactory创建一个XmlBeanDefinitionReader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 为beanDefinitionReader进行环境变量设置
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// 对beanDefinitionReader进行设置,可以覆盖
initBeanDefinitionReader(beanDefinitionReader);
// 进行配置文件读取
loadBeanDefinitions(beanDefinitionReader);
}
// XmlBeanDefinitionReader中已经将之前初始化的DefaultListableBeanFactory注册进去了,所以XmlBeanDefinitionReader所读取的
// BeanDefinitionHolder都会注册到DefaultListableBeanFactory中,也就是经过此步骤,
// 类型DefaultListableBeanFactory的变量beanFactory已经包含了所有解析好的配置.
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
3.这个方法开始创建(非懒加载)对象,finishBeanFactoryInitialization();
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 初始化此上下文的转换服务
// 这是spring3以后新加的代码,为容器指定一个转换服务(ConversionService)
// 在这对某些bean属性进行转换时使用
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));
}
// 如果没有bean后置处理程序,则注册一个默认的嵌入式解析器
// (例如PropertyPlaceholderConfigurer bean)在此之前注册: 此时,主要用于解析注释属性值。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// 尽早初始化LoadTimeWeaverAware bean,以循序尽早注册它们的转换器。
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// 为了类型匹配,停止使用临时的类加载器
beanFactory.setTempClassLoader(null);
// 缓存容器中所注册的BeanDefination元数据,以防被修改
beanFactory.freezeConfiguration();
// 实例化所有剩余的非lazy-init单例
beanFactory.preInstantiateSingletons();
}
// 这里调用了ConfigurableListableBeanFactory中的preInstantiateSingletons()方法
// 其实现类为DefaultListableBeanFactory(Spring初始化创建的bean工厂),所以说这个方法是spring的bean工厂中执行的,该bean工厂在经过上面XmlBeanDefinitionReader读取配置信息,已经包含了所有解析好的配置(比如在xml中配置的bean信息)
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Pre-instantiating singletons in " + this);
}
// 从bean工厂中取出,按注册顺序排列的bean定义名称集合
List<String> beanNames = new ArrayList(this.beanDefinitionNames);
Iterator var2 = beanNames.iterator();
// 触发所有非惰性单例的bean的初始化
while(true) {
String beanName;
Object bean;
do {
while(true) {
RootBeanDefinition bd;
do {
do {
do {
if (!var2.hasNext()) {
var2 = beanNames.iterator();
// 扫描所有的bean
while(var2.hasNext()) {
beanName = (String)var2.next();
// 从缓存中获取对应的bean
Object singletonInstance = this.getSingleton(beanName);
// 判断创建的对象是否实现SmartInitializingSingleton接口
if (singletonInstance instanceof SmartInitializingSingleton) {
// 如果存在实现SmartInitializingSingleton接口的bean,
// 那么Spring还会调用该bean的afterSingletonsInstantiated()方法
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, this.getAccessControlContext());
} else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
return;
}
beanName = (String)var2.next();
// 根据beanName获取对应的RootBeanDefinition信息
bd = this.getMergedLocalBeanDefinition(beanName);
} while(bd.isAbstract()); // 判断bean定义信息是否为抽象类
} while(!bd.isSingleton()); // 判断bean定义信息是否为单例
} while(bd.isLazyInit()); // 判断bean定义信息是否为懒加载
// 判断当前类是否为工厂bean // 如果指定名称的bean是创建容器的bean
if (this.isFactoryBean(beanName)) {
// FACTORY_BEAN_PREFIX="&",当bean名称前面加"&"符号时,
// 获取的是产生容器对象本身,而不是容器产生的bean
// 调用getBean()方法,不存在就创建,触发容器对bean实例化和依赖注入过程
bean = this.getBean("&" + beanName);
break;
}
// 调用getBean()方法,不存在就创建,触发容器对bean实例化和依赖注入过程
this.getBean(beanName);
}
} while(!(bean instanceof FactoryBean));
FactoryBean<?> factory = (FactoryBean)bean;
// 判断是否需要预实例化
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
SmartFactoryBean var10000 = (SmartFactoryBean)factory;
((SmartFactoryBean)factory).getClass();
isEagerInit = (Boolean)AccessController.doPrivileged(var10000::isEagerInit, this.getAccessControlContext());
} else {
isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
}
if (isEagerInit) {
// 调用getBean()方法,不存在就创建,触发容器对bean实例化和依赖注入过程
this.getBean(beanName);
}
}
}
该方法实现了从bean工厂中获取注册的beanName信息,并依次遍历,若为单例对象则调用getBean方法,触发容器对Bean实例化和依赖注入过程。
最后将创建好的bean注入到这个缓存池map中
// FactoryBean的缓存池
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
// 单例缓存池
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
四、获取bean
我们平常使用的context.getBean(“”);
调用的屙屎ApplicationContext里的getBean方法,我们知道BeanFactory中有getBean的方法,ApplicationContext又集成BeanFactory,其实调用的就是BeanFactory中的getBean方法