上一篇文章,我门已经了解了Spring容器初始化的过程。初始化过程中会将单例
、非抽象的
、非懒加载
的Bean创建好并放进缓存中以供使用。Bean的生命周期也就是指创建、使用、销毁的全过程,下面就此展开。
Bean的生命周期
大白话概述一下Bean的创建:
我们知道对象(即Bean)的创建一般使用new
或者反射的方式创建,Spring就是采用反射的方式来创建Bean。Spring Bean的创建包括了实例化
、属性赋值
、初始化
,经过以上三步就能完成Bean的创建。但Spring既然是框架,就要给使用者多提供一些拓展点,让用户扩展,所以在Bean的生命周期中,会有9个
BeanPostProcessor
以及一些可以拓展的接口。
这些后置处理器干嘛用的?说白了就是每个Bean创建时候都去遍历一下当前的后置处理器,看是否需要被处理一下。遍历的时机也是有好几处。
有了拓展点以外,还有一个棘手的问题就是Bean间循环依赖(A依赖B,B依赖A)的问题,以及循环依赖下AOP(需要创建代理对象,并把代理对象赋值给被依赖Bean)。为了解决这个问题,Spring是借助一、二、三级缓存和后置处理器来实现的,循环依赖的具体细节将在下一篇文章阐述。
实例化前
try {
/**
* 第1个bean后置处理器
* aop和事务的关键,因为在这里解析我们的aop切面信息进行缓存
*/
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
//判断容器中是否有InstantiationAwareBeanPostProcessors
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
/**
* 后置处理器的【第一次】调用 总共有九处调用 事务在这里不会被调用,aop的才会被调用
* 为啥aop在这里调用了,因为在此处需要解析出对应的切面放到缓存中
*/
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
// 一般情况下返回的都是null
// 如果不为null说明生成了代理对象那么我们就调用
if (bean != null) {
/**
* 后置处理器的第二处调用,该后置处理器若被调用的话,那么第一处的处理器肯定返回的不是null
* InstantiationAwareBeanPostProcessors后置处理器postProcessAfterInitialization
*/
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
实例化
if (instanceWrapper == null) {
// 实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
@Autowired预处理
try {
// 第3个bean后置处理器
// 进行后置处理 @AutoWired @Value的注解的预解析
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
实例化后的Bean放三级缓存
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
//上述条件满足,允许早期暴露对象
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//把我们的早期对象包装成一个singletonFactory对象 该对象提供了一个getObject方法,
// 该方法内部调用getEarlyBeanReference方法,该方法再去调后置处理器
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
填充属性
// 填充属性
populateBean(beanName, mbd, instanceWrapper);
初始化
// aware方法、初始化前、初始化、 初始化后
exposedObject = initializeBean(beanName, exposedObject, mbd);
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 执行aware方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 执行before处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 执行初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 执行after方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
销毁
@Override
public void close() {
synchronized (this.startupShutdownMonitor) {
doClose();
// If we registered a JVM shutdown hook, we don't need it anymore now:
// We've already explicitly closed the context.
if (this.shutdownHook != null) {
try {
Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
}
catch (IllegalStateException ex) {
// ignore - VM is already shutting down
}
}
}
}
@PostConstruct
最后提一点。很多人觉得这个注解标记的方法,是在Bean初始化阶段的invokeInitMethods(beanName, wrappedBean, mbd);
里边执行的,
其实是在初始化阶段的applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
执行的