Spring源码(三)Spring Bean的生命周期

了解专栏完整的内容,请点击跳转:
Spring Framework专栏导航页

gitee注释版源码


上一篇文章,我门已经了解了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);执行的
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值