你好,我柳岸花开。
在使用Spring框架时,我们经常会听到关于Bean的生命周期的概念。本文将深入探讨Bean的生命周期,从Bean的生成到销毁,逐步解析Spring框架中的关键步骤。
什么是Bean的生命周期?
Bean的生命周期指的是Bean在Spring容器中的生成、初始化、使用和销毁的整个过程。在这个过程中,Spring框架负责管理Bean的创建和销毁,同时允许开发者通过扩展点来干预Bean的行为,以满足特定需求。
Bean的生成过程
在Spring中,Bean的生成过程是通过IOC(控制反转)实现的。下面我们来详细了解一下Bean的生成过程:
// 入口代码
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
生成BeanDefinition:
在Spring启动时,会扫描指定的包路径,得到所有的BeanDefinition。
扫描类文件流程如下:
-
首先,通过ResourcePatternResolver获得指定包路径下的所有.class文件(Spring源码中将此文件包装成了Resource对象) -
遍历每个Resource对象 -
利用MetadataReaderFactory解析Resource对象得到MetadataReader(在Spring源码中MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory,MetadataReader的具体实现类为SimpleMetadataReader) -
利用MetadataReader进行excludeFilters和includeFilters,以及条件注解@Conditional的筛选(条件注解并不难理解:某个类上是否存在@Conditional注解,如果存在则调用注解中所指定的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉。) -
筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition -
再基于metadataReader判断是不是对应的类是不是接口或抽象类 -
如果筛选通过,那么就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集。
CachingMetadataReaderFactory解析某个.class文件得到MetadataReader对象是利用的ASM技术,并没有加载这个类到JVM。最终得到的ScannedGenericBeanDefinition对象,beanClass属性存储的是当前类的名字,而不是class对象。(beanClass属性的类型是Object,它即可以存储类的名字,也可以存储class对象)
为什么要使用ASM技术,Spring启动的时候需要去扫描,如果指定的包路径比较宽泛,那么扫描的类是非常多的,那如果在Spring启动时就把这些类全部加载进JVM了,这样不太好,所以使用了ASM技术。
ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能; .class字节码是有严格的格式的,ASM可以通过格式来解析字节码,得到类名称、方法、属性等信息; ASM比jdk反射技术性能更高; JVM类加载是懒加载的,通过ASM来获取类信息,更节省JVM性能;
合并BeanDefinition:
Spring支持父子BeanDefinition的合并,以及工厂方法创建Bean。
加载类:
根据BeanDefinition中的类名加载对应的类,这一步是实例化对象的前提条件。
// 加载类
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (mbd.hasBeanClass()) {
// 如果beanClass属性的类型是Class,那么就直接返回
return mbd.getBeanClass();
}
// 根据类名加载
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
// 利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()所返回的类加载器来加载。
return doResolveBeanClass(mbd, typesToMatch);
}
实例化前扩展点:
Spring提供了InstantiationAwareBeanPostProcessor扩展点,允许在实例化对象之前进行一些操作。
// 实例化前扩展点
@Component
public class BobBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// 注意,此时还没有实例化,所以能拿到的是beanClass
if ("userService".equals(beanName)) {
System.out.println("实例化前");
// 可以返回值,非null时,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步
return new UserService();
}
return null;
}
}
实例化Bean:
根据BeanDefinition创建对象实例,可以通过Supplier创建、工厂方法创建或者推断构造方法创建等方式。
BeanDefinition的后置处理:
Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(),可以对此时的BeanDefinition进行加工。
@Component
public class BobMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if ("userService".equals(beanName)) {
beanDefinition.getPropertyValues().add("orderService", new OrderService());
}
}
}
在Spring源码中,AutowiredAnnotationBeanPostProcessor就是一个MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()中会去查找注入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中(injectionMetadataCache)。
实例化后:
在处理完BeanDefinition后,Spring又设计了一个扩展点:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()。
@Component
public class BobInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
UserService userService = (UserService) bean;
userService.test();
}
return true;
}
}
处理属性:
这个步骤中,就会处理@Autowired、@Resource、@Value等注解,也是通过InstantiationAwareBeanPostProcessor.postProcessProperties()扩展点来实现的。
@Component
public class BobInstantiationAwareBeanPostProcessor 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(FireInject.class)) {
field.setAccessible(true);
try {
field.set(bean, "123");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return pvs;
}
}
执行Aware:
完成了属性赋值之后,Spring会执行一些回调,包括:
BeanNameAware:回传beanName给bean对象。
BeanClassLoaderAware:回传classLoader给bean对象。
BeanFactoryAware:回传beanFactory给对象。
初始化前:
初始化前,也是Spring提供的一个扩展点:BeanPostProcessor.postProcessBeforeInitialization()。 利用初始化前,可以对进行了依赖注入的Bean进行处理。
@Component
public class BobBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化前");
}
return bean;
}
}
InitDestroyAnnotationBeanPostProcessor会在初始化前这个步骤中执行@PostConstruct的方法, ApplicationContextAwareProcessor会在初始化前这个步骤中进行其他Aware的回调:
- EnvironmentAware:回传环境变量
- EmbeddedValueResolverAware:回传占位符解析器
- ResourceLoaderAware:回传资源加载器
- ApplicationEventPublisherAware:回传事件发布器
- MessageSourceAware:回传国际化资源
- ApplicationStartupAware:回传应用其他监听对象,可忽略
- ApplicationContextAware:回传Spring容器ApplicationContext
初始化
-
查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法 -
执行BeanDefinition中指定的初始化方法
初始化后
这是Bean创建生命周期中的最后一个步骤,也是Spring提供的一个扩展点:BeanPostProcessor.postProcessAfterInitialization()。 可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象。
@Component
public class FireBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化后");
}
return bean;
}
}
总结
-
实例化前(InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()) -
实例化 -
合并Bean(MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()) -
实例化后(InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()) -
自动注入 -
属性赋值(InstantiationAwareBeanPostProcessor.postProcessProperties()) -
Aware对象 -
初始化前(BeanPostProcessor.postProcessBeforeInitialization()) -
初始化 -
初始化后(BeanPostProcessor.postProcessAfterInitialization())
Bean的销毁过程
与生成过程相对应,Bean的销毁过程发生在Spring容器关闭时。下面是Bean销毁的主要步骤:
// Bean的销毁过程
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();
// 容器关闭
context.close();
在Spring容器关闭过程时:
-
首先发布ContextClosedEvent事件 -
调用lifecycleProcessor的onCloese()方法 -
销毁单例Bean
1.遍历disposableBeans,把每个disposableBean从单例池中移除,调用disposableBean的destroy()。如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean;如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉。
2.清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanName
3.清空allBeanNamesByType,是一个Map,key是bean类型,value是该类型所有的beanName数组
4.清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean
最后
通过以上步骤,我们可以清晰地了解Spring框架中Bean的生命周期。掌握Bean的生命周期对于深入理解Spring框架的运作机制和实现原理非常重要,也有助于我们在实际开发中更好地利用Spring框架的功能。
希望本文能够帮助您更好地理解Spring中Bean的生命周期,如果有任何疑问或意见,请随时留言交流。
本文由 mdnice 多平台发布