Spring最核心的功能之一就是创建对象(IOC)
Bean的生命周期指:在spring中,一个Bean的生成和销毁的过程
1. 生成BeanDefinition
Spring启动先进行扫描,调用
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents(String basePackage)
扫描路径,得到BeanDefinition的Set集合
1.1扫描的流程
- 首先,通过
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
加入结果集
MetadataReader
表示类的元数据读取器,主要包含了一个AnnotationMetadata
,功能有:
- 获取类的名字
- 获取父类的名字
- 获取所实现的所有接口名
- 获取所有内部类的名字
- 判断是不是抽象类
- 判断是不是接口
- 判断是不是一个注解
- 获取拥有某个注解的方法集合
- 获取类上添加的所有注解信息
- 获取类上添加的所有注解类型集合
CachingMetadataReaderFactory
解析某个.class文件得到MetadataReader对象是 利用的ASM技术,并没有加载这个类到JVM。并且,最终得到的ScannedGenericBeanDefinition
对 象,beanClass属性存储的是当前类的名字,而不是class对象。(beanClass属性的类型是Object, 它即可以存储类的名字,也可以存储class对象)
另外还可以通过直接定义BeanDefinition,或 解析spring.xml文件的,或者@Bean注解得到BeanDefinition对象。
1.2 合并BeanDefinition
Spring中支持父子BeanDefinition
// child是单例Bean
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child"/>
// child就是原型Bean
// child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child" parent="parent"/>
根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的 BeanDefinition。
1.3 加载类
根据合并之后的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()所返回的类加载器来加载
- 优先返回当前线程中的ClassLoader
- 线程中类加载器为null的情况下,返回ClassUtils类的类加载器
- 如果ClassUtils类的类加载器为空,那么则表示是Bootstrap类加载器加载的ClassUtils类,那么 则返回系统类加载器
1.4 实例化前
在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean 实例化之前做一些启动动作。这个扩展点叫 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
@Component
public class CustomBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化之前");
return new UserService();
}
return null;
}
}
这个方法有返回值,如果像上述的实现则表示不需要spring 来实例化,并且后续spring依赖注入等步骤也不会进行,直接执行初始化后这一步了
1.5 实例化
根据Beandefinition
创建对象
1.5.1 Supplier创建对象
首先会判断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);
1.5.2 工厂方法创建对象
接着会检查是否设置了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();
}
}
需要注意的是,我们通过@Bean
所定义的BeanDefinition
,是存在factoryMethod
和factoryBean
的,也就是和上面的方式二非常类似,@Bean所注解的方法就是factoryMethod,AppConfig对象 就是factoryBean。如果@Bean所所注解的方法是static的,那么对应的就是方式一。
1.5.3 推断构造方法
在推断构造方法中除了选择构造方法和查找入参对象以外,还会判断是否在对应类中使用Lookup
注解的方法,如果存在就会将该方法封装为lookupOverride
对象添加到BeanDefinition
中
在实例化时如果没有LookupOverride
对象会直接用构造方法反射生成实例对象,如果存在则生成一个代理对象
// @Lookup注解就是方法注入
@Component
public class UserService {
private OrderService orderService;
public void test() {
OrderService orderService = createOrderService();
System.out.println(orderService);
}
@Lookup("orderService")
public OrderService createOrderService() {
return null;
}
}
1.6 BeanDefinition的后置处理
Bean对象实例化之后就该给对象赋值了,在赋值之前,spring有提供了一个扩展点,可以对BeanDefinition
加工
MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
@Component
public class CustomMergedBeanDefinitionPostProcessor 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
)
1.7 实例化后
在处理完BeanDefinition
后,Spring又设计了一个扩展点,对所实例化出来的对象进行处理。InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
@Component
public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
UserService userService = (UserService) bean;
userService.test();
}
return true;
}
}
1.8 自动注入
spring的自动注入,依赖注入部分详解
1.9 处理属性
这个步骤中,就会处理@Autowired、@Resource、@Value等注解,也是通过 InstantiationAwareBeanPostProcessor.postProcessProperties()
扩展点来实现的,比如我们 甚至可以实现一个自己的自动注入功能,比如
// @CustomInject自定义注解标识的字段设置值
@Component
public class CustomInstantiationAwareBeanPostProcessor 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(.class)) {
field.setAccessible(true);
try {
field.set(bean, "123");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return pvs;
}
}
1.10 执行Aware
完成了属性赋值之后,Spring会执行一些回调,包括:
- BeanNameAware:回传beanName给bean对象。
- BeanClassLoaderAware:回传classLoader给bean对象。
- BeanFactoryAware:回传beanFactory给对象。
1.11 初始化前
初始化前,也是Spring提供的一个扩展点: BeanPostProcessor.postProcessBeforeInitialization()
@Component
public class CustomBeanPostProcessor 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的回调:- EnvironmentAware:回传环境变量
- EmbeddedValueResolverAware:回传占位符解析器
- ResourceLoaderAware:回传资源加载器
- ApplicationEventPublisherAware:回传事件发布器
- MessageSourceAware:回传国际化资源
- ApplicationStartupAware:回传应用其他监听对象,可忽略
- ApplicationContextAware:回传Spring容器ApplicationContext
1.12 初始化
- 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet() 方法
- 执行BeanDefinition中指定的初始化方法
1.13 初始化后
这是Bean创建生命周期中的最后一个步骤,也是Spring提供的一个扩展点: BeanPostProcessor.postProcessAfterInitialization()
可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返 回的对象才是最终的Bean对象。
public static void main(String[] args) {
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化后");
}
return bean;
}
}
}
1.14 总结BeanPostProcessor
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
- 实例化
- MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
- 自动注入
- InstantiationAwareBeanPostProcessor.postProcessProperties()
- Aware对象
- BeanPostProcessor.postProcessBeforeInitialization()
- 初始化
- BeanPostProcessor.postProcessAfterInitialization()
2.Bean的销毁过程
Bean销毁是发生在Spring容器关闭过程中
AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();
// 容器关闭
context.close();
在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是 DisposableBean
-
当前Bean是否实现了
DisposableBean
接口 -
或者,当前Bean是否实现了
AutoCloseable
接口 -
BeanDefinition中是否指定了
destroyMethod
-
调用
DestructionAwareBeanPostProcessor.requiresDestruction(bean)
进行判断-
ApplicationListenerDetector
中直接使得ApplicationListener
是DisposableBean
-
InitDestroyAnnotationBeanPostProcessor
中使得拥有@PreDestroy
注解了的方法就是DisposableBean
-
-
把符合上述任意一个条件的Bean适配成
DisposableBeanAdapter
对象,并存入disposableBeans
中(一个LinkedHashMap)
在spring容器关闭时:
-
首先发布
ContextClosedEvent
事件 -
调用
lifecycleProcessor
的onCloese()
方法 -
销毁单例Bean
-
遍历
disposableBeans
-
把每个
disposableBean
从单例池中移除 -
调用
disposableBean
的destroy()
-
如果这个
disposableBean
还被其他Bean依赖了,那么也得销毁其他Bean -
如果这个
disposableBean
还包含了inner beans,将这些Bean从单例池中移除掉(inner bean参考链接)
-
-
清空
manualSingletonNames
,是一个Set,存的是用户手动注册的单例Bean的 beanName -
清空
allBeanNamesByType
,是一个Map,key是bean类型,value是该类型所有的 beanName数组 -
清空
singletonBeanNamesByType
,和allBeanNamesByType
类似,只不过只存了单例 Bean
-
这里涉及到一个设计模式:适配器模式
在销毁时,Spring会找出实现了DisposableBean
的Bean,有上述几类情况。
这些Bean在容器关闭时都要调用相应的销毁方法。 所以,这里就需要进行适配,将实现了DisposableBean
接口、或者AutoCloseable
接口等适配成实现了DisposableBean
接口,所以就用到了DisposableBeanAdapter
。
会把实现了AutoCloseable
接口的类封装成DisposableBeanAdapter
,而DisposableBeanAdapter
实现了DisposableBean
接口