Spring Bean的生命周期

前言

Spring Bean 是 Spring IOC 容器负责实例化、组装和管理的对象,它和普通的 Java 对象并没有什么区别,唯一的区别就是它不是由开发人员自己 new 出来的,而是由容器负责创建的。IOC 容器除了实例化对象,还会负责管理对象之间的依赖关系,自动注入依赖和属性,甚至创建代理对象来对原始对象进行增强。

生命周期是一个对象从创建到被销毁经历的整个过程,普通Java对象的生命周期是JVM分配内存,调用构造函数实例化对象,当该对象没有被引用后再由GC负责销毁并释放内存。而 Spring Bean 是由IOC容器负责创建和管理的对象,它的生命周期相比普通Java对象会更加复杂。

生命周期

Spring Bean 的生命周期简单来说可以划分为五大阶段:实例化 -> 属性赋值 -> 初始化 -> 对外服务 -> 销毁。

实例化

生命周期的第一阶段是实例化,Spring 首先得要有Bean的定义才知道该如何实例化,这个Bean的定义就是 BeanDefinition。不论是通过@Component 注解定义的Bean,还是通过xml配置的Bean,Spring 最终都会把它们解析并封装成 BeanDefinition 对象。

Spring 创建Bean的入口是AbstractAutowireCapableBeanFactory#createBean ,这里会触发扩展点 InstantiationAwareBeanPostProcessor,给BeanPostProcessor一个返回代理对象的机会,跳过 Spring Bean 的创建流程。如果扩展点没有返回代理对象就会调用doCreateBean() 创建Bean。

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
   
	RootBeanDefinition mbdToUse = mbd;
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
   
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	try {
   
		mbdToUse.prepareMethodOverrides();
	} catch (BeanDefinitionValidationException ex) {
   
		throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
				beanName, "Validation of method overrides failed", ex);
	}

	try {
   
		/**
		 * 调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
		 * 给BeanPostProcessor一个返回代理对象的机会,跳过Spring Bean创建流程
		 */
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
   
			return bean;
		}
	} catch (Throwable ex) {
   
		throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
				"BeanPostProcessor before instantiation of bean failed", ex);
	}
	try {
   
		// 创建bean
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
   
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	} catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
   
		throw ex;
	} catch (Throwable ex) {
   
		throw new BeanCreationException(
				mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
	}
}

doCreateBean() 里首先会调用createBeanInstance() 实例化Bean,有三种方式:

  • 调用 instanceSupplier 实例化
  • 触发 factoryMethodName 实例化
  • 推断构造函数,反射调用实例化

紧接着调用populateBean() 完成属性填充、注入依赖,再是initializeBean() 初始化Bean,最后是把Bean注册到disposableBeans 在容器销毁时触发destroy-method。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
   
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
   
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	if (instanceWrapper == null) {
   
		// 实例化bean
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
   
		mbd.resolvedTargetType = beanType;
	}
	synchronized (mbd.postProcessingLock) {
   
		if (!mbd.postProcessed) {
   
			try {
   
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			} catch (Throwable ex) {
   
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}
	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");
		}
		addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
	}

	Object exposedObject = bean;
	try {
   
		// 属性填充
		populateBean(beanName, mbd, instanceWrapper);
		// 初始化bean
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	} catch (Throwable ex) {
   
		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
   
			throw (BeanCreationException) ex;
		} else {
   
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
		}
	}

	if (earlySingletonExposure) {
   
		Object earlySingletonReference = getSingleton(beanName, false);
		if (earlySingletonReference != null) {
   
			if (exposedObject == bean) {
   
				exposedObject = earlySingletonReference;
			} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
   
				String[] dependentBeans = getDependentBeans(beanName);
				Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
				for (String dependentBean : dependentBeans) {
   
					if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
   
						actualDependentBeans.add(dependentBean);
					}
				}
				if (!actualDependentBeans.isEmpty()) {
   
					throw new BeanCurrentlyInCreationException(beanName,
							"Bean with name '" + beanName + "' has been injected into other beans [" +
									StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
									"] in its raw version as part of a circular reference, but has eventually been " +
									"wrapped. This means that said other beans do not use the final version of the " +
									"bean. This is often the result of over-eager type matching - consider using " +
									"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
				}
			}
		}
	}

	try {
   
		// 必要时注册到disposableBeans,容器销毁时调用destroy-method
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	} catch (BeanDefinitionValidationException ex) {
   
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}
	return exposedObject;
}

属性填充

生命周期的第二阶段是属性填充,在填充前 Spring 得知道要为Bean填充哪些属性,所以会先触发 MergedBeanDefinitionPostProcessor 扩展点收集填充的元数据 InjectionMetadata,包含被@Autowired、@Value、@Resource注解的属性或方法。还有生命周期方法元数据 LifecycleMetadata,也就是Bean的 init-method、destroy-method等。
元数据收集完毕后,开始调用populateBean() 填充属性。属性填充前,会触发扩展点InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 返回值告诉 Spring 是否要继续填充属性,默认返回 true。之后会调用InstantiationAwareBeanPostProcessor#postProcessProperties 扩展点来填充属性。
以 AutowiredAnnotationBeanPostProcessor 为例,它会收集被@Autowired注解的方法和属性元数据,并且注入对应的属性值。

初始化

生命周期的第三阶段是初始化,initializeBean() 首先会触发几个Aware接口方法,然后触发BeanPostProcessor#postProcessBeforeInitialization 扩展点,接着触发 init-method,如果Bean实现了InitializingBean接口,会再触发InitializingBean#afterPropertiesSet ,最后触发BeanPostProcessor#postProcessAfterInitialization 扩展点。

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 {
   
		// 触发BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
		invokeAwareMethods(beanName, bean);
	}
	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
   
		// 扩展点 BeanPostProcessor#postProcessBeforeInitialization
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}
	try {
   
		// 执行init方法 InitializingBean#afterPropertiesSet
		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()) {
   
		// 扩展点 BeanPostProcessor#postProcessAfterInitialization
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

对外服务

初始化以后,Bean就是一个完整可用的Bean了,此时就可以正常对外服务了。

销毁

生命周期的第五阶段是销毁,ConfigurableApplicationContext 在close时会触发destroyBeans() ,它会遍历 disposableBeans 并调用DisposableBeanAdapter#destroy ,如果Bean实现了DisposableBean接口,则调用DisposableBean#destroy ;如果Bean实现了AutoCloseable接口,则调用AutoCloseable#close ;如果Bean指定了destroyMethod,则触发对应的销毁方法。

至此,Spring Bean的整个生命周期就结束了,为了便于记忆,画了个脑图
image.png

尾巴

Spring Bean的生命周期大致可以分为:实例化 -> 属性填充 -> 初始化 -> 对外服务 -> 销毁 五个阶段。Spring 会把 BeanClass或者xml配置解析成BeanDefinition,根据定义会有三种实例化Bean的方式,Bean的实例化前后会有对应的扩展点。实例化完成以后,Spring 会触发扩展点来收集要注入的元数据和生命周期方法元数据,然后调用扩展点完成属性注入。之后就是初始化节点,会先触发几个Aware接口方法,再触发BeanPostProcessor前置扩展点,然后执行 init-method,接着触发BeanPostProcessor后置扩展点,Bean就可以对外提供服务了。最后在容器关闭时,Spring 还会调用Bean的销毁方法,整个生命周期就结束了。

相关推荐

  1. springbean生命周期

    2024-02-19 13:20:02       37 阅读
  2. Vue生命周期

    2024-02-19 13:20:02       63 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-19 13:20:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-19 13:20:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-02-19 13:20:02       82 阅读
  4. Python语言-面向对象

    2024-02-19 13:20:02       91 阅读

热门阅读

  1. git提交代码冲突

    2024-02-19 13:20:02       50 阅读
  2. 第13章 网络 Page818 UDP(和TCP的比较)

    2024-02-19 13:20:02       43 阅读
  3. 解决 error: ‘make_unique’ is not a member of ‘std’

    2024-02-19 13:20:02       43 阅读
  4. 【C++】并查集

    2024-02-19 13:20:02       55 阅读
  5. 常用工具记录

    2024-02-19 13:20:02       48 阅读
  6. 2024前端面试准备之CSS篇(二)

    2024-02-19 13:20:02       61 阅读
  7. g++编译--运行opencv步骤。

    2024-02-19 13:20:02       45 阅读
  8. alibaba的fastjson怎么将json字符串转换为范型对象

    2024-02-19 13:20:02       48 阅读
  9. 动态规划-简单举例-青蛙跳台阶

    2024-02-19 13:20:02       51 阅读