Spring Bean的生命周期

本文详细阐述了Spring中Bean的生命周期,从BeanDefinition的生成、Bean的创建过程(包括生成、合并、加载类、实例化前、实例化、BeanDefinition后置处理等步骤)到Bean的销毁过程,揭示了Spring如何管理Bean的整个生命周期。内容涵盖实例化前后的扩展点、自动注入、Aware接口回调以及初始化前后的方法执行。


请添加图片描述

生命周期图

Bean生命周期含义:在Spring中,一个Bean是如何生成的,如何销毁的
Bean 生命周期

Bean扫描

在这里插入图片描述在这里插入图片描述

Bean 的创建过程

1. 生成BeanDefinition

  1. 通过ResourcePatternResolver获取指定路径下所有的.class文件(封装为Resource对象)
  2. 遍历所有Resource对象
  3. 利用MetadataReaderFactory(具体实现类:CachingMetadataReaderFactory)解析Resource对象获得MetadataReader(具体实现类:SimpleMetadataReader)
  4. 通过MetadataReader来进行excludeFiltersincludeFilters过滤,并通过条件注解@Condition进行筛选(如果有@Condition注解则调用match()方法进行匹配筛选)
  5. 基于metadataReader生成对应的ScannedGenericBeanDefination
  6. 再次基于metadataReader进行筛选(判断是否为非顶级类、非静态内部类、接口、抽象类等)
  7. 通过筛选的类,将其ScannedGenericBeanDefinition加入结果集(扫描到一个Bean)

除了扫描生成BeanDefinition对象之外,还可以通过直接定义BeanDefinition,或解析spring.xml配置文件中的<bean/>,或用@Bean注解得到BeanDefinition对象。

MetadataReader 作用

  1. 类名
  2. 父类名
  3. 所有实现的接口名
  4. 所有内部类名
  5. 是否为抽象类
  6. 是否为接口
  7. 是否是一个注解
  8. 获取已有的注解的所有方法集合
  9. 获取所有注解信息
  10. 获取所有注解类型集合

CachingMetadataReaderFactory解析.class文件得到的MetadataReader对象是通过ASM技术获取的,并未去加载这个类!!!

得到的SccannedGenericBeanDefinition对象中,beanClass属性存储的只是当前类的名字,并非class对象! (beanClass属性的类型为Object,既可以存储类的名字(String),也可以存储class对象(Class<?>))

2.合并BeanDefinition

在 Spring 中,支持父子 BeanDefinition!
可以通过父子BeanDefinition继承一些属性。

<bean id="parent" class="Parent" scope="prototype"/>
<bean id="child" class="Child" parent="parent"/>

在该例子中,由于 child 指定父亲 BeanDefinition 为 parent ,因此继承 parent 中的 scope 属性的值 prototype。

而在根据 child 来生成 Bean 对象之前,需要进行 BeanDefinition 的合并,才能得到完整的 child 的 BeanDefinition。

-> MergedBeanDefinition

3.加载类

合并 BeanDefinition 后便可以创建 Bean 对象,而创建 Bean 对象就必须要 实例化 对象, 因此需要先加载当前 BeanDefinition 对应的 class

AbstractAutowireCapableBeanFactory 的 createBean() 方法中:

Class<?> resolvedClass = resolveBeanClass(mdb, beanName);

resolveBeanClass() 方法便是去加载类的。

if (mbd.hasBeanClass()) {
   
   
	return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
   
   
	return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) ()>
	doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
} else {
   
   
	return doResolveBeanClass(mbd, typesToMatch);
}

hasBeanClass() :
判读 beanClass 属性是否为 Class 实例(是否被加载过)

public boolean hasBeanClass() {
   
   
	return (this.beanClass instance Class);
}

会使用 BeanFactory 所设置的类加载器来加载类,如果没有设置类加载器,则默认使用 ClassUtils.getDefaultClassLoader() 返回的类加载器来加载。

ClassUtils.getDefaultClassLoader()

  1. 优先返回当前线程中的 ClassLoader
  2. 线程中类加载器为 null 时,返回 ClassUtils 类的类加载器
  3. 如果 ClassUtils 类的类加载器为 null ,则表示由 Bootsrap 类加载器加载的 ClassUtils 类,那么直接返回系统类加载器

4.实例化前

在类被加载后,实例化前,Spring 提供了一个扩展点,允许用户来控制是否在某个或某些 Bean 实例化前做一些启动动作。

扩展点:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()

实现 InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation()方法

/**
	当每有一个 Bean 对象实例化前,会打印 “实例化前”
*/
@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
   
   
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
	throws BeansException {
   
   
		System.out.println("实例化前");
		return null;
	}
}

注意:
postProcessBeforeInstantiation() 是有返回值的,如果返回非空对象,则会在实例化前直接返回我们返回的对象。如果这样做,则表示不需要再由 Spring 来实例化,并且后续的 Spring 依赖注入也不会再进行!直接执行初始化后这一阶段。


@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   
   
	Object bean = null
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值