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;
	if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
		// Make sure bean class is actually resolved at this point.
		// synthetic表示合成,如果某些Bean式合成的,那么则不会经过BeanPostProcessor的处理
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			Class<?> targetType = determineTargetType(beanName, mbd);
			if (targetType != null) {
				bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
				if (bean != null) {
					bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
				}
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
}

5.实例化

5.1 Supplier 创建对象

首先检测 BeanDefinition 中是否设置了 Supplier ,如果存在则调用 Supplier 的 get() 方法获取对象。

// BeanDefinition中添加了Supplier,则调用Supplier来得到对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
	return obtainFromSupplier(instanceSupplier, beanName);
}

5.2 工厂方法创建对象

如果没有设置 Supplier ,则检查 BeanDefinition 中是否设置了 factoryMethod,也就是工厂方法。(两种设置 factoryMethod的方式)

// @Bean对应的BeanDefinition
if (mbd.getFactoryMethodName() != null) {
	return instantiateUsingFactoryMethod(beanName, mbd, args);
}

方式一: 指定 factoryMethod 为当前类的方法

<bean id="userService" class="UserService" factory‐
method="createUserService" />

对应的 UserService 类:

public class UserService {
	public static UserService createUserService() {
		System.out.println("执行createUserService()");
		UserService userService = new UserService();
		return userService;
	}
}

方式二: 指定 factoryMedthod 为其他类的方法

<bean id="commonService" class="CommonService"/>
<bean id="userService" factory‐bean="commonService" factory‐method="createUserService"
/>

对应的 CommonService 类:

public class CommonService {
	public UserService createUserService() {
		return new UserService();
	}
}

若设置了 工厂方法,则 Spring 会调用工厂方法获取对象。

注意:
如果通过 @Bean 注解定义的 BeanDefinition,也是存在 factoryMethod 和 factoryBean 的!与 方式二 类似,@Bean 所注解的方法就是 factoryMetod, 所在的类的对象就是 factoryBean。 如果 @Bean 所注解的方法是 static 的,则对应 方式一。

5.3 推断构造方法

根据传入的参数推断使用的构造方法,用它来实例化。

在推断构造方法逻辑中,除去选择构造方法与查找入参对象之外,还会判断是否在对应的类中是否存在 @Lookup 注解的方法。 如果存在,则把该方法封装为 LookupOverride 对象并添加到 BeanDefinition 中。

在实例化时,如果当前 BeanDefinition 中存在 LookupOverride 对象(该类存在 @Lookup注解了的方法)则会生成一个 代理对象;否则直接反射调用构造方法获取一个实例对象。

@Looup 注解就是 方法注入

@Component
public class UserService {
	private OrderService orderService;
	public void test() {
		OrderService orderService = createOrderService();
		System.out.println(orderService);
	}
	@Lookup("orderService")
	public OrderService createOrderService() {
		return null;
	}
}

6. BeanDefinition 的后置处理

实例化 Bean 之后,接下来需要给对象属性赋值。在真正给属性赋值之前, Spring 提供了一个扩展点
MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
可以对当前的 BeanDefinition 加工!

在 Spring 源码中,AutowiredAnnotationBeanPostProcessor 就是一个 JMergedBeanDefinitionPostProcessor,它的 postProcessMergedBeanDefinition() 会去查找注入点,并缓存在 AutowiredAnnotationBeanPostProcessor 对象的一个 Map 中(injectionMetadataCache)。

7.实例化后

在处理完 BeanDefinition 后,Spring还提供了一个扩展点:
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
返回值类型为 boolean,如果返回 false 则会结束后续的postProcessAfterInstantitaion()postProcessPropertiesValues()的执行!!!


boolean continueWithPropertyPopulation = true;

if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
				continueWithPropertyPopulation = false;
				break;
			}
		}
	}
}

if (!continueWithPropertyPopulation) {
	return;
}


但是该扩展点在 Spring 中基本没有被使用到。

8.自动注入

9.处理属性

处理 @Autowired 、@Resource 、@Value 等注解,都是通过实现 InstantiationAwareBeanPostProcessor.postProcessProperties() 扩展点来实现的。

这个方法通常是给目标 bean 设值,这个过程发生只有在postProcessAfterInstantiation() 方法的结果返回 true 才会被执行!

@Component
public class MyInstantiationAwareBeanPostProcessor implements
InstantiationAwareBeanPostProcessor {
	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			for (Field field : bean.getClass().getFields()) {
				if (field.isAnnotationPresent(ZhouyuInject.class)) {
					field.setAccessible(true);
					try {
						field.set(bean, "123");
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return pvs;
	}
}

在 AbstractAutowireCapableBeanFactory 类的方法 populateBean 中会执行到该扩展点:


boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

if (hasInstAwareBpps || needsDepCheck) {
	PropertyDescriptor[] filteredPds = 
			filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
	if (hasInstAwareBpps) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = 
									(InstantiationAwareBeanPostProcessor) bp;
				pvs = ibp.postProcessPropertyValues(pvs, filteredPds, 
								bw.getWrappedInstance(), beanName);
				if (pvs == null) {
					return;
				}
			}
		}
	}
	if (needsDepCheck) {
		checkDependencies(beanName, mbd, filteredPds, pvs);
	}
}

applyPropertyValues(beanName, mbd, bw, pvs);

可以看到,如果这个方法返回为空,也不会对目标bean设值

10. 执行部分 Aware

在完成属性赋值后,Spring 还会调用一些列实现了 Aware 接口的回调方法。

  1. BeanNameAware: 将 beanName 注入到 bean 对象中
  2. BeanClassLoaderAware: 将 classLoader 注入到 bean 对象中
  3. BeanFactoryAware
private void invokeAwareMethods(String beanName, Object bean) {
	if (bean instanceof Aware) {
		if (bean instanceof BeanNameAware) {
			((BeanNameAware) bean).setBeanName(beanName);
		}
		if (bean instanceof BeanClassLoaderAware) {
			ClassLoader bcl = getBeanClassLoader();
			if (bcl != null) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
			}
		}
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}

11. 初始化前

在初始化前 Spring 提供了一个扩展点:
BeanPostProcessor.postProcessBeforeInitialization()

@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	return bean;
}  
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

返回值:可以是原始的Bean实例,也可以是包装的Bean实例;如果为空,则不会调用后续的 BeanPostProcessors 的 postProcessBeforeInitialization() 方法!

@PostConstruct

InitDestroyAnnotationBeanPostProcessor 会在初始前执行有 @PostConstruct 注解的方法。

ApplicationContextAwareProcessor

ApplicationContextAwareProcessor 会在初始化前进行其他 Aware 的回调。

  1. EnvironmentAware:回传环境变量
  2. EmbeddedValueResolverAware:回传占位符解析器
  3. ResourceLoaderAware:回传资源加载器
  4. ApplicationEventPublisherAware:回传事件发布器
  5. MessageSourceAware:回传国际化资源
  6. ApplicationStartupAware:回传应用其他监听对象,可忽略
  7. ApplicationContextAware:回传Spring容器ApplicationContext

12. 初始化

InitializingBean

如果 Bean 对象实现了 InitializingBean 接口,则调用其 afterPropertiesSet() 方法

boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
	if (logger.isTraceEnabled()) {
		logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
	}
	if (System.getSecurityManager() != null) {
		try {
			AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
				((InitializingBean) bean).afterPropertiesSet();
				return null;
			}, getAccessControlContext());
		}
		catch (PrivilegedActionException pae) {
			throw pae.getException();
		}
	}
	else {
		((InitializingBean) bean).afterPropertiesSet();
	}
}

BeanDefinition 中指定的初始化方法

执行 BeanDefinition 中指定的初始化方法

if (mbd != null && bean.getClass() != NullBean.class) {
	String initMethodName = mbd.getInitMethodName();
	if (StringUtils.hasLength(initMethodName) &&
			!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
			!mbd.isExternallyManagedInitMethod(initMethodName)) {
		invokeCustomInitMethod(beanName, bean, mbd);
	}
}

13. 初始化后

这是 Bean 创建生命周期中的最后一个步骤,也是 Spring 提供的一个扩展点
BeanPostProcessor.postProcessAfterInitialization()

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;

	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

若返回 null ,则会提前结束,取消执行后续的 BeanPostProcessor 的 postProcessAfterInitialization() 方法!

Bean 的销毁过程

Bean 销毁是发生在 Spring 容器关闭过程中的。context.close()

判断是否属于 DisposableBean

在 Bean 创建过程中,初始化后,会去判断当前创建的 Bean 是否属于 DisposableBean

  1. 是否实现 DisposableBean 接口
  2. 是否实现 AutoCloseable 接口
  3. BeanDefinition 中是否指定了 destroyMethod
  4. DestructionAwareBeanPostProcessor.requiresDestruction(bean) 中判断
    • ApplicationListenerDetector:是否实现 ApplicationListener
    • InitDestroyAnnotationBeanPostProcessor: 检测是否有 @PreDestroy 注解的方法
  5. 将符合以上任意一个条件的 Bean 适配成 DisposableBeanAdapter 对象,并存储在 disposableBeans 中(一个 LinkedHashMap)

销毁过程

  1. 首先发布 ContextClosedEvent 事件
  2. 调用 lifecycleProcessor 的 onClose() 方法
  3. 销毁单例 Bean
    • 遍历 disposableBeans
      • 把每个 disposableBean 从单例池中移除
      • 调用 disposableBean 的 destroy()
      • 如果该 disposableBean 被其他 Bean 依赖,则同时销毁其他 Bean
      • 如果该 disposableBean 包含 inner beans ,则将这些 Bean 从单例池中移除
    • 清空 manualSingletonNames(存储着 用户手动注册 的单例 Bean 的 beanName 的 Set)
    • 清空 allBeanNamesByType(Map<Class<?>,String[]>)
    • 清空 singletonBeanNamesByType(只存储了单例Bean)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值