[TOC]
- Bean的生命周期就是指:
- 在Spring中,一个Bean是如何生成的,如何销毁的
- Spring启动的时候,会进行扫描,调用如下方法:
- 扫描某个包路径,并得到 BeanDefinition 的 Set 集合
- 首先,通过
ResourcePatternResolver
获得指定包路径下的所有.class
文件- Spring源码中将这些文件包装成了
Resource
对象
- Spring源码中将这些文件包装成了
- 遍历每个
Resource
对象 - 利用
MetadataReaderFactory
解析Resource
对象,得到MetadataReader
- Spring源码中,MetadataReaderFactory 具体实现类为
CachingMetadataReaderFactory
- MetadataReader 具体实现类为
SimpleMetadataReader
- Spring源码中,MetadataReaderFactory 具体实现类为
- 利用
MetadataReader
进行excludeFilters
和includeFilters
,以及条件注解@Conditional
的筛选- 某个类上是否存在 @Conditional 注解
- 存在则调用注解中,所指定的类的
match
方法进行匹配- 匹配成功则通过筛选
- 匹配失败则pass掉
- 存在则调用注解中,所指定的类的
- 某个类上是否存在 @Conditional 注解
- 筛选通过后,基于
MetadataReader
生成ScannedGenericBeanDefinition
- 再基于
MetadataReader
判断,对应的类是不是 接口或抽象类 - 如果筛选通过,表示扫描到了一个bean,将
ScannedGenericBeanDefinition
加入结果集
- 表示类的元数据读取器,主要包含一个
AnnotationMetadata
- 功能有:
- 获取类的名字
- 获取父类的名字
- 获取所实现的所有接口名
- 获取所有内部类的名字
- 判断是不是抽象类
- 判断是不是接口
- 判断是不是一个注解
- 获取拥有某个注解的方法集合
- 获取类上添加的所有注解信息
- 获取类上添加的所有注解类型集合
CachingMetadataReaderFactory
解析某个 .class 文件,得到 MetadataReader 对象- 是使用的
ASM
技术 - 并没有加载这个类到 JVM
- 是使用的
- 并且,最终得到的
ScannedGenericBeanDefinition
对象- beanClass 属性,存储的是当前类的名字,而不是 class 对象
- beanClass 的类型是 Object
- 上面说的是,通过扫描得到
BeanDefinition
- 还可以直接定义 BeanDefinition
- 或解析 spring.xml 中的
- 或@Bean注解得到的 BeanDefinition
- 通过扫描,得到所有 BeanDefinition 后
- 就可以根据 BeanDefinition 创建 bean 对象了
- Spring 中支持 父子BeanDefinition
- 实际使用较少
- 案例如下:
<!-- child是单例bean -->
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child"/>
<!-- child是原型bean -->
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child" parent="parent"/>
- child 会继承 parent 上所定义的 scope 属性
- 在根据 child 生成 bean 对象之前
- 需要进行 BeanDefinition 合并,得到完整的 child 的 BeanDefinition
- BeanDefinition 合并后,就可以创建 bean 对象了
- 创建 bean 就必须实例化对象
- 实例化就必须先加载当前 BeanDefinition 所对应的 class
- 在
AbstractAutowireCapableBeanFactory # createBean()
中- 一开始就会调用:
// 加载类
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
// 方法实现
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
return doResolveBeanClass(mbd, typesToMatch);
}
public boolean hasBeanClass() {
return (this.beanClass instanceof Class);
}
- 如果 beanClass 属性的类型是 Class,则直接返回
- 如果不是,则根据类名进行加载
- doResolveBeanClass() 做的事
- 会利用 BeanFactory 所设置的类加载器来加载类
- 如果没有设置,则默认使用
ClassUtils.getDefaultClassLoader()
所返回的类加载器来加载
- 如果没有设置,则默认使用
ClassUtils.getDefaultClassLoader()
:- 优先返回当前线程中的 ClassLoader
- 线程中类加载器为 null 的情况下,返回 ClassUtils 的类加载器
- 如果 ClassUtils 的类加载器为空,则表示 Bootstrap 加载的
- 那么返回 系统类加载器
- 当前 BeanDeifinition 对应的类加载成功后,就可以实例化对象了
- 在Spring中,实例化对象之前,提供了一个扩展点
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
- 允许用户控制,是否在某个或某些 bean 实例化之前,做一些启动动作
- 举例:
// 在 userService 实例化前,进行打印
@Component
public class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
}
return null;
}
}
postProcessBeforeInstantiation()
是有返回值的- 举例如下,直接返回自定义的一个 UserService 对象
- 表示不需要 Spring 来实例化了,后续的 依赖注入 也不会进行了
- 跳过一些步骤,直接执行 初始化后 这一步
@Component
public class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
return new UserService();
}
return null;
}
}
- 根据 BeanDefinition 创建一个对象
-
首先判断 BeanDefinition 中是否设置了
Supplier
- 如果设置了则调用 Supplier 的 get() 得到对象
-
得直接使用 BeanDefinition 对象来设置 Supplier
- 举例:
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setInstanceSupplier(new Supplier<Object>() {
@Override
public Object get() {
return new UserService();
}
});
context.registerBeanDefinition("userService", beanDefinition);
-
如果没有设置 Supplier,则检查 BeanDefinition 中是否设置了 factoryMethod,即工厂方法
-
有两种方式可以设置 factoryMethod
-
方式一:
-
<bean id="userService" class="com.zhouyu.service.UserService" factory-method="createUserService" />
-
public class UserService { public static UserService createUserService() { System.out.println("执行createUserService()"); UserService userService = new UserService(); return userService; } public void test() { System.out.println("test"); } }
-
-
方式二:
-
<bean id="commonService" class="com.zhouyu.service.CommonService"/> <bean id="userService1" factory-bean="commonService" factory-method="createUserService" />
-
public class CommonService { public UserService createUserService() { return new UserService(); } }
-
-
-
Spring发现当前 BeanDefinition 设置了 factoryMethod 后,就会区分这两种方式,然后调用 factoryMethod 得到对象
-
注意:
- 通过 @Bean 定义的 BeanDefinition,是存在 factoryMethod 和 factoryBean 的
- 和上面的方式二非常类似
- @Bean 所注解的方法就是 factoryMethod
- AppConfig 对象就是 factoryBean
- 如果 @Bean 所注解的方式是 static 的,那么对应的就是 方式一
- 推断完构造方法后,就使用构造方法来进行实例化
- 在推断构造方法逻辑中,除了 选择构造方法 以及 查找入参对象外
- 还会判断 在对应的类中是否存在
@Lookup
注解的方法 - 如果存在,则将该方法封装为
LookupOverride
对象、并添加到 BeanDefinition 中
- 还会判断 在对应的类中是否存在
- 在实例化时,如果判断出来当前 BeanDefinition 中没有 LookupOverride
- 就直接用 构造方法 反射,得到一个实例对象
- 如果存在 LookupOverride 对象,也就是类中存在 @Lookup 注解的方法,就会生成一个代理对象
- @Lookup 注解就是
方法注入
,使用 demo 如下:
@Component
public class UserService {
private OrderService orderService;
public void test() {
OrderService orderService = createOrderService();
System.out.println(orderService);
}
@Lookup("orderService")
public OrderService createOrderService() {
return null;
}
}
- Bean对象实例化出来后,就该给对象的属性进行赋值了
- 在真正属性赋值之前,Spring又提供了一个扩展点:
MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinitio()
- 可以对此时的 BeanDefinition 进行加工,举例如下:
@Component
public class ZhouyuMergedBeanDefinitionPostProcessor 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()
- 对实例化出来的对象进行处理(这个扩展点,Spring源码中基本没怎么使用)
- 举例如下:
@Component
public class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
UserService userService = (UserService) bean;
userService.test();
}
return true;
}
}
- 这里指 Spring自动注入
- 这个步骤中,就会处理 @Autowired、@Resource、@Value 等注解
- 也是通过
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
实现的 - 案例:实现一个自己的自动注入功能
@Component
public class ZhouyuInstantiationAwareBeanPostProcessor 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;
}
}
- 属性赋值之后,Spring会执行一些回调,包括:
- BeanNameAware:回传 beanName 给 bean
- BeanClassLoaderAware:回传 classLoader 给 bean
- BeanFactoryAware:回传 beanFactory 给对象
- 也是 Spring 提供的一个扩展点
BeanPostProcessor.postProcessBeforeInitialization()
- 举例:
@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化前");
}
return bean;
}
}
- 在初始化前,可以对进行了 依赖注入 的 bean 做处理
- 在 Spring 源码中
InitDestroyAnnotationBeanPostProcessor
会在初始化前这个步骤,执行 @PostConstruct 方法ApplicationContextAwareProcessor
会在初始化前这个步骤,进行其他 Aware 的回调- EnviromentAware:回传环境变量
- EmbeddedValueResolverAware:回传占位符解析器
- ResourceLoaderAware:回传资源加载器
- ApplicationEventPublisherAware:回传事件发布器
- MessageSourceAware:回传国际化资源
- ApplicationStartupAware:回传应用其他监听对象,可忽略
- ApplicationContextAware:回传Spring容器ApplicationContext
- 查看当前 bean 对象是否实现了
InitializingBean
接口- 如果实现了,就调用其
afterPropertiesSet()
方法
- 如果实现了,就调用其
- 执行 BeanDefinition 中指定的初始化方法
- bean 创建生命周期中的最后一个步骤,Spring也提供了一个扩展点
BeanPostProcessor.postProcessAfterInitialization()
- 举例如下:
@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化后");
}
return bean;
}
}
- 在这个步骤中,对 bean 最终进行处理
- Spring 中 AOP 就是基于
初始化后
实现的 - 初始化后返回的对象,才是最终的 bean 对象
- Spring 中 AOP 就是基于
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
- 实例化
- MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
- 自动注入
- InstantiationAwareBeanPostProcessor.postProcessProperties()
- Aware对象
- BeanPostProcessor.postProcessBeforeInitialization()
- 初始化
- BeanPostProcessor.postProcessAfterInitialization()
- bean的销毁,是发生在 Spring 容器关闭过程中的
- 举例如下:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();
// 容器关闭
context.close();
- 实例化之后,会有一个步骤,判断当前创建的 bean 是不是 DisposableBean
- 当前 bean 是否实现了 DisposableBean
- 或者,当前 bean 是否实现了 AutoCloseable 接口
- BeanDefinition 中是否指定了 destroyMethod
- 调用 DestructionAwareBeanPostProceesor.requiresDestruction(bean) 进行判断
- ApplicationListenerDetector 中,直接使得 ApplicationListener 是 DisposableBean
- InitDestroyAnnotationBeanPostProcessor 中,使得 @PreDestroy 注解了的方法,就是 DisposableBean
- 把符合上述任意一个条件的 bean,适配成 DisposableBeanAdapter 对象
- 并存入 disposableBeans 中(一个 LinkedHashMap)
- 首先发布 ContextClosedEvent 事件
- 调用 lifecycleProcessor 的 onCloese() 方法
- 销毁单例 bean
- 遍历 disposableBeans
- 将每个遍历到的 disposableBean 从单例池中移除
- 调用 disposableBean 的 destroy()
- 如果这个 disposableBean 还被其他 bean 依赖了,那么也得销毁其他 bean
- 如果这个 disposableBean 还包含了 inner beans,将这些 bean 从单例池中移除掉
- 清空 manualSingletonNames(一个Set,存的用户手动注册的单例bean 的 beanName)
- 清空 allBeanNamesByType(一个Map,key是bean类型,value是该类型所有的beanName数组)
- 清空 singletonBeanNamesByType,和 allBeanNamesByType 类似,只不过只存了单例bean
- 遍历 disposableBeans
- 销毁时,Spring会找出实现了 DisposableBean 接口的 bean
- 但在定义 bean 时,以下几种方式的bean、都需要调用相应销毁方法
- 实现了 DisposableBean 接口
- 实现了 AutoCloseable 接口
- BeanDefinition 中指定了 destroyMethodName
- 所以,这里就需要适配,就用上了
DisposableBeanAdapter
- 将上面的 bean 类都封装成 DisposableBeanAdapter
- 而 DisposableBeanAdapter 实现了 DisposableBean 接口