Spring Bean的生命周期(一图流+详细说明)

在我的博客阅读本文

1. 前言

Spring是一个IOC(Inversion of Control,控制反转)容器框架,拥有DI(Dependency Injection,依赖注入)DL(Dependency Lookup,依赖查找 等功能。

认为一个IOC框架最基本要有以下功能:

  • 配置解析
  • 对象创建
  • 对象生命周期管理

本文基于Spring-5.2.2.RELEASE版本进行论述,为了简明扼要,在展示部分代码的时候省略了一些细节。

Spring Bean的生命周期总结因为没有一个正式的文档,因此是一个比较偏主观的分享,笔者只能结合小马哥的观点与自身的认识情况大概进行了总结,主要思路还是围绕着方法的调用栈,笔者认为,写在一个方法里,那么就可以认为是一个阶段。

2. Spring Bean生命周期

这里po一张我自己画的图:

Spring%20Bean%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%200e4b70a5ffd54a4bb12cc41b2dfe98d6/Untitled.png

我将SpringBean生命周期分为以下五个阶段:

  1. 注册阶段
  2. 合并阶段
  3. 实例化阶段
  4. 初始化阶段
  5. 销毁阶段

下面具体看一下每个阶段所做的事情。

2.1. 注册阶段

注册阶段的主要任务是通过各种BeanDefinitionReader读取各种配置来源信息(比如读取xml文件、注解等),并将其转化为BeanDefintion的过程。

这里要理解一下BeanDefinition的作用。众所周知,Spring提供了多种多样的注册Bean的方法,BeanDefinition的作用就是去定义并描述一个Spring Bean,方便后续解析实例化等操作。

ApplicationContext#register()方法完成了对象注册阶段,其最终是调用的DefaultListableBeanFactory#registerBeanDefinition() 完成的BeanDefinition注册,这里的“注册”意思是将配置信息转化为BeanDefinition并放到合适的容器中,我们可以看以下代码:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
   

	/** Map of bean definition objects, keyed by bean name. */
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

	/** List of bean definition names, in registration order. */
	private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

	//省略部分代码......
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
   
				//省略了一些判断代码......
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
	}
}

其中,beanDefinitionMap的数据结构是ConcurrentHashMap,因此不能保证顺序,为了记录注册的顺序,这里使用了ArrayList类型的beanDefinitionNames用来记录注册顺序。

2.2. 合并阶段

经过了注册阶段,Spring的BeanDefinition容器中已经有了部分BeanDefinition信息(可能还存在通过aware接口或者postProcessor接口注册进来的beanDefinition),下面分为两种情况:

  • 对于设置了非懒加载属性的BeanDefinition,在容器启动时(ApplicationContext#refresh())时会最终调用BeanFactory#getBean()方法进行实例化
  • 对于懒加载(isLazyInit)的BeanDefinition,则需要在用到的时候调用BeanFactory#getBean()方法进行实例化。

事实上,无论哪种情况,Spring最终都会调用BeanFactory#getBean()方法进行实例化。在getBean()方法中会有一个合并阶段:

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
   
	protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
   
		//......
		final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
		//......
	}
}

AbstractBeanFactory#getMergedLocalBeanDefinition()方法完成了BeanDefinition的合并,这里的“合并”的意思是,部分BeanDefinition可能不是RootBeanDefinition(没有parent),而是部分属性需要继承其他BeanDefinition,比如xml配置中的parent属性,这就需要进行一次合并,最终产出RootBeanDefinition。

RootBeanDefinition的parent设置时候会有一个判断,可以看出来,RootBeanDefinition最典型的特点就是没有parent reference:

public class RootBeanDefinition extends AbstractBeanDefinition {
   
	//......
	@Override
	public void setParentName(@Nullable String parentName) {
   
		if (parentName != null) {
   
			throw new IllegalArgumentException("Root bean cannot be changed into a child bean with parent reference");
		}
	}
	//......
}

2.3. 实例化阶段

到了实例化阶段,Spring将转化BeanDefinition中BeanDefinition为实例Bean(放在包装类BeanWrapper中)。

2.3.1. 通过ClassLoader赋值BeanDefinition的beanClass为Class对象

我们首先关注到AbstractAutowireCapableBeanFactory#createBean()方法,AbstractAutowireCapableBeanFactory是DefaultListableBeanFactory的父类,在这个方法中有个过程:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
      implements AutowireCapableBeanFactory {
   
	//......
	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
   

		if (logger.isTraceEnabled()) {
   
			logger.trace("Creating instance of bean '" + beanName + "'");
		}
		RootBeanDefinition mbdToUse = mbd;

		//......

		// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
   
				return bean;
		}
		//......

		// Make sure bean class is actually resolved at this point, and
		// clone the bean definition in case of a dynamically resolved Class
		// which cannot be stored in the shared merged bean definition.
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		if (resolvedClass != null && !mbd.hasBeanClass
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值