spring bean的生命周期详解

 2022-09-04
原文地址:https://blog.csdn.net/qq_41571395/article/details/124607111

序言

Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象做准备,所以我们先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。

流程图

202209042312581771.png

具体过程

这里省略了一些逻辑,bean生命周期主要逻辑如下

1.创建BeanFactory

    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

spring启动在applicationContext时会构造一个BeanFactory对象

2.扫描

Spring启动的时候会进行扫描,会先调用

    org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandid
    ateComponents(String basePackage)

扫描某个包路径,并得到BeanDefinition的Set集合。
扫描的逻辑也是比较复杂,后面有时间的话再拿出来单独讲。

3.合并BeanDefinition

由于Spring中支持父子BeanDefinition,所以需要进行BeanDefinition的合并,得到完整的child的BeanDefinition。(很少用这样定义)

    <bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
    <bean id="child" class="com.zhouyu.service.Child"/>

4.加载类

BeanDefinition合并之后,就可以去创建Bean对象了,而创建Bean就必须实例化对象,而实例化就必须先加载当前BeanDefinition所对应的class
如果beanClass属性的类型是Class,那么就直接返回,如果不是,则会根据类名进行加载(doResolveBeanClass方法所做的事情)会利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用
ClassUtils.getDefaultClassLoader()所返回的类加载器来加载。

5.实例化前

当前BeanDefinition对应的类成功加载后,就可以实例化对象了,但是…
在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean实例化之前做一些启动动作。这个扩展点叫InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()。比如:

    @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;
    	}
    }

如上代码会导致,在userService这个Bean实例化前,会进行打印。
值得注意的是,postProcessBeforeInstantiation()是有返回值的,如果这么实现:

    @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;
    	}
    }

userService这个Bean,在实例化前会直接返回一个由我们所定义的UserService对象。如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。

6. 实例化

在这个步骤中就会根据BeanDefinition去创建一个对象了。
这里实例化的时候涉及到知识点 推断构造方法大家可以看我的另一篇博客

7. BeanDefinition的后置处理

Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点
MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(),可以对此时的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)。

8. 实例化后

在处理完BeanDefinition后,Spring又设计了一个扩展点:
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(),比如:

    @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;
    	}
    }

上述代码就是对userService所实例化出来的对象进行处理。
这个扩展点,在Spring源码中基本没有怎么使用。

9. 填充填充

这里的自动注入指的是Spring的自动注入,也就是填充属性(依赖注入)
这个步骤中,就会处理@Autowired、@Resource、@Value等注解,
这其中的逻辑也比较复杂,后面有时间的话再拿出来单独讲。

10. 执行Aware

完成了属性赋值之后,Spring会执行一些回调,包括:

  1. BeanNameAware:回传beanName给bean对象。
  2. BeanClassLoaderAware:回传classLoader给bean对象。
  3. BeanFactoryAware:回传beanFactory给对象。

11. 初始化前

初始化前,也是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进行处理。

12. 初始化

  1. 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法
  2. 执行BeanDefinition中指定的初始化方法

13. 初始化后

这是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对象。

14.bean销毁

Bean销毁是发送在Spring容器关闭过程中的。
在Spring容器关闭时,比如:

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    UserService userService = (UserService) context.getBean("userService");
    userService.test();
    // 容器关闭
    context.close();

在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是DisposableBean:

  1. 当前Bean是否实现了DisposableBean接口
  2. 或者,当前Bean是否实现了AutoCloseable接口
  3. BeanDefinition中是否指定了destroyMethod
  4. 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
    i. ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
    ii. InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是
    DisposableBean
  5. 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入
    disposableBeans中(一个LinkedHashMap)

在Spring容器关闭过程时:

  1. 首先发布ContextClosedEvent事件

  2. 调用lifecycleProcessor的onCloese()方法

  3. 销毁单例Bean

    1. 遍历disposableBeans

      1. 把每个disposableBean从单例池中移除
      2. 调用disposableBean的destroy()
      3. 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
      4. 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉(inner bean参考https://docs.spring.io/springframework/docs/current/springframework-reference/core.html#beans-inner-beans)
    2. 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanNam

    3. 清空allBeanNamesByType,是一个Map,key是bean类型,value是该类型所有的beanName数组

    4. 清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean