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

Bean扫描


Bean 的创建过程
1. 生成BeanDefinition
- 通过
ResourcePatternResolver获取指定路径下所有的.class文件(封装为Resource对象) - 遍历所有
Resource对象 - 利用
MetadataReaderFactory(具体实现类:CachingMetadataReaderFactory)解析Resource对象获得MetadataReader(具体实现类:SimpleMetadataReader) - 通过
MetadataReader来进行excludeFilters和includeFilters过滤,并通过条件注解@Condition进行筛选(如果有@Condition注解则调用match()方法进行匹配筛选) - 基于
metadataReader生成对应的ScannedGenericBeanDefination - 再次基于
metadataReader进行筛选(判断是否为非顶级类、非静态内部类、接口、抽象类等) - 通过筛选的类,将其
ScannedGenericBeanDefinition加入结果集(扫描到一个Bean)
除了扫描生成BeanDefinition对象之外,还可以通过直接定义BeanDefinition,或解析spring.xml配置文件中的<bean/>,或用@Bean注解得到BeanDefinition对象。
MetadataReader 作用
- 类名
- 父类名
- 所有实现的接口名
- 所有内部类名
- 是否为抽象类
- 是否为接口
- 是否是一个注解
- 获取已有的注解的所有方法集合
- 获取所有注解信息
- 获取所有注解类型集合
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()
- 优先返回当前线程中的 ClassLoader
- 线程中类加载器为 null 时,返回 ClassUtils 类的类加载器
- 如果 ClassUtils 类的类加载器为 null ,则表示由 Bootsrap 类加载器加载的 ClassUtils 类,那么直接返回系统类加载器
4.实例化前
在类被加载后,实例化前,Spring 提供了一个扩展点,允许用户来控制是否在某个或某些 Bean 实例化前做一些启动动作。
扩展点:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
实现 InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法
/**
当每有一个 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

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

被折叠的 条评论
为什么被折叠?



