Bean的生命周期

一、BeanDefinition

什么是BeanDefinition,从英文的名字中我们就可以知道它是用来定义Bean的

docs.spring.io/spring-fram…

image-20210608205037114.png

bean的创建是根据我们提供的一些配置的元数据,比如xml。在容器里,这些由我们配置的元数据被表示为BeanDefinition

image-20210608205457827.png

二、bean的生命周期概述

1.实例化bean(createBeanInstance)

该阶段主要是实例化出一个bean对象,主要通过反射以及cglib动态字节码生成对象(可以理解为new了一个对象出来了)

2.属性赋值(populateBean)

该阶段主要是用于给bean对象的属性赋值(比如设置了@Autowired的属性赋值)

思考:Spring如何解决循环依赖

3.bean的初始化(initializeBean)

调用org.springframework.beans.factory.InitializingBean接口的afterPropertiesSet() 以及调用我们指定的init-method(例如xml的init-method、@Bean的init参数)

思考:@PostConstruct是在这个阶段完成的吗

以上的三个阶段,是Bean创建的三个阶段,对应代码里的这三个部分

image-20210619104307334.png

4.使用中

bean的使用阶段,也是业务调用的阶段

5.销毁

调用destroy的方法

6.Bean生命周期(创建)的泳道图:

image.png

三、bean的创建——实例化bean(InstanceBean)

image.png
从代码看,我们知道InstanceBean分为几种实例化方式

1.通过factoryBean实例化(红框1)

是否使用BeanDefinition里面的factoryMethod实例化(@Bean注解是使用工厂方法实例化的,实例化的方式可以自定义)

2.通过带参构造器实例化(红框2)

使用autowireConstructor方法构建(会递归实例化构造器入参的bean)

3.通过无参构造器实例化(红框3)

对于创建bean的方式2和方式3,最终都是通过反射或者cglib字节码实例化对象

四、bean的创建——属性赋值(PopulateBean)

“wecom-temp-170fe36fa94a4dc442316371d6466abb”的副本.png

可以看到,我分别框了四个红框,这四个红框分别是这个PopulateBean的主要的两个步骤

1.InstantiationAwareBeanPostProcessor的实例化后置处理(postProcessBeforeInstantiation)。(红框1)

由于这部分是实例化的后置处理,这里我们讲的是属性赋值,我们先暂时忽略这部分代码

2.属性自动装配初始化。(红框2)

这部分是获取BeanDefinition里面的resolvedAutowireMode(自动装配模式)。然后根据自动装配的模式(根据属性类型装配AUTOWIRE_BY_TYPE或者根据属性名装配AUTOWIRE_BY_NAME)查找bean中的set方法,然后匹配对应的属性,查找或递归创建出对应的bean,放到pvs(PropertyValues)里面。

1.AutowireMode自动装配模式的配置在@Bean的注解的autowire属性,xml的autowire属性写入

2.除了@Bean的注解的autowire属性,xml的autowire属性写入,还以通过修改BeanDefinition,典型使用——MyBatis,definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)

3.如果不设置,都是默认AUTOWIRE_NO,即不进行属性的自动装配

4.可以看到我的描述,这部分代码并没有将属性赋值给bean,只是获取到后放pvs(PropertyValues)里面,赋值的操作是第四个红框

5.AutowireMode和注解@Autowire没有任何关系

3.InstantiationAwareBeanPostProcessor的属性值处理(postProcessPropertyValues)。(红框3)

这部分代码是@Autowire等注解注入的主要地方

InstantiationAwareBeanPostProcessor有多个实现类,代码中遍历了多个实现类去装配属性。

例如:

  • AutowiredAnnotationBeanPostProcessor实现装配@Autowired、@Inject和@Value
  • CommonAnnotationBeanPostProcessor实现装配@Resource、@WebServiceRef、@EJB
  • ……

4.属性自动装配赋值(红框4)

将红框2中拿到的属性赋值到当前的bean即applyPropertyValues部分的代码

5.总结

总结:PopulateBean的逻辑其实主要就两个

一个是通过自动装配的模式对set方法对应的属性进行装配,主要有三种

  • AUTOWIRE_NO(默认,不进行属性自动装配)
  • AUTOWIRE_BY_NAME(通过属性名进行自动装配)
  • AUTOWIRE_BY_TYPE(通过属性类型进行自动装配)

另外一个是通过循环调用InstantiationAwareBeanPostProcessor#postProcessPropertyValues方法对属性进行注入,@Autowired、@Resource、@Value等注解都是在这里进行属性注入的

五、bean的创建——bean的初始化(InitializeBean)

image-20210624192228486.png

代码这里我圈了四个红框,我们只需要关注第三个红框就行

  • 红框1是判断是否是BeanNameAware、BeanClassLoaderAware和BeanFactoryAware接口,如果是,则要分别注入beanName、classLoader和beanFactory,这里我们先忽略
  • 红框2是调用BeanPostProcessor#postProcessBeforeInitialization执行初始化的前置操作,这里我们先忽略
  • 红框3是初始化的主代码,执行初始化方法invokeInitMethods
  • 红框4是调用BeanPostProcessor#postProcessAfterInitialization执行初始化的后置操作,这里我们先忽略

接下来我们来看一下初始化的主方法invokeInitMethods里面主要是干了什么

image-20210624193009599.png

1.遍历执行InitializingBean#afterPropertiesSet方法

使用场景:策略模式+afterPropertiesSet

2.执行bean执行的初始化方法(init-method)

bean的初始化方法的指定通常可以通过注解org.springframework.context.annotation.Bean#initMethod或者xml的init-method的属性来指定。具体实现的逻辑是通过反射来调用改方法

六、bean创建的三个阶段的总结

  • InstanceBean
    • 通过factoryBean实例化
    • 通过带参构造器实例化
    • 通过无参构造器实例化
  • PopulateBean
    • AutowireMode
      • AUTOWIRE_NO(默认,不进行属性自动装配)
      • AUTOWIRE_BY_NAME(通过属性名进行自动装配)
      • AUTOWIRE_BY_TYPE(通过属性类型进行自动装配)
    • InstantiationAwareBeanPostProcessor#postProcessPropertyValues对@Autowired、@Resource、@Value等注解进行属性赋值
  • InitializeBean
    • 执行InitializingBean#afterPropertiesSet方法
    • 执行init-method(@Bean#initMethod和xml的init-method)

image.png

七、bean生命周期的扩展点

我们将开展点分成两类

  • Bean的生命周期成员InitializingBean、DisposableBean
  • Bean的生命周期的重要参与者InstantiationAwareBeanPostProcessor、BeanPostProcessor

1.InitializingBean/DisposableBean接口

InitializingBean接口对应bean初始化,DisposableBean对应bean的销毁,这两个接口类似,我们只挑InitializingBean进行讲解

image-20210624202001520.png

InitializingBean接口只有一个方法afterPropertiesSet,bean对应的类实现了这个接口就能是在bean初始化阶段处理一些事情。

2.BeanPostProcessor接口

BeanPostProcessor接口影响到了bean的初始化阶段

image-20210624202448382.png

它一共有两个接口

  • BeanPostProcessor#postProcessBeforeInitialization
  • BeanPostProcessor#postProcessAfterInitialization

顾名思义,一个是初始化阶段前调用,一个是初始化阶段后调用,调用处详见五、bean的创建——bean的初始化(InitializeBean)的红框2和红框4

BeanPostProcessor#postProcessAfterInitialization的典型使用AOP、@PostConstruct

3.InstantiationAwareBeanPostProcessor接口

InstantiationAwareBeanPostProcessor接口参与到了Bean的实例化、属性赋值、以及初始化阶段

image-20210624202754202.png

它一共有五个接口

  • InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

bean实例化(InstanceBean)前调用,是整个创建bean的前置逻辑,在这里可以自己创建bean,创建完之后就直接返回了,不走Spring创建bean的逻辑

image-20210625194709118.png

  • InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

bean实例化(InstanceBean)后调用,属性赋值(PopulateBean)前调用,调用处详见四、bean的创建——属性赋值(PopulateBean)的红框1

  • InstantiationAwareBeanPostProcessor#postProcessPropertyValues

属性赋值(PopulateBean)的主逻辑之一,CommonAnnotationBeanPostProcessor实现了这个方法对@Resource的属性赋值,AutowiredAnnotationBeanPostProcessor实现了这个方法对@Value、@Autowired的属性赋值,调用处详见四、bean的创建——属性赋值(PopulateBean)的红框3

  • BeanPostProcessor#postProcessBeforeInitialization

同BeanPostProcessor

  • BeanPostProcessor#postProcessAfterInitialization

同BeanPostProcessor

八、各式各样的为Aware接口

Aware接口主要分成两类

1.BeanNameAware、BeanClassLoaderAware和BeanFactoryAware接口

这三个接口在BeanPostProcessor#postProcessBeforeInitialization之前执行,这几个接口不参与到bean的创建中,只是用来获取某些东西,调用处详见五、bean的创建——bean的初始化(InitializeBean)的红框1

2.其他的Aware接口

这些接口也都不参与到Bean的创建中,也是用来获取某些东西,通过BeanPostProcessor#postProcessBeforeInitialization注入到Bean中

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	@Override
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {

		invokeAwareInterfaces(bean);

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

}

复制代码
  • EnvironmentAware获取Spring配置文件
  • EmbeddedValueResolverAware获取Spl解析器
  • ApplicationContextAware(ResourceLoaderAware\ApplicationEventPublisherAware\MessageSourceAware)获取bean对象
  • ……

九、总结

  • 创建的三个阶段
    • bean的实例化
      • 通过factoryBean实例化
      • 带参构造器实例化
      • 无参构造器实例化
    • bean的属性赋值
      • 设置AutowireMode赋值
      • 实现InstantiationAwareBeanPostProcessor#postProcessPropertyValues接口赋值
    • bean的初始化
      • 运行的init-method方法
      • 运行InitializingBean#afterPropertiesSet接口
  • 两个生命周期接口
    • InitializingBean#afterPropertiesSet(属于bean的初始化阶段)
    • DisposableBean#destroy(属于bean的销毁阶段)
  • 两个生命周期参与接口
    • BeanPostProcessor
      • postProcessBeforeInitialization(bean初始化阶段前置调用)
      • postProcessAfterInitialization(bean初始化后置调用)
    • InstantiationAwareBeanPostProcessor
      • postProcessAfterInstantiation(bean实例化阶段前置调用)
      • postProcessBeforeInstantiation(bean实例化阶段的后置调用)
      • postProcessPropertyValues(bean的属性赋值中的一种)
      • postProcessBeforeInitialization(bean的初始化阶段的前置调用)
      • postProcessAfterInitialization(bean的初始化阶段的后置调用)
  • 各种各种各样的Aware接口
    • BeanNameAware、BeanClassLoaderAware和BeanFactoryAware接口
    • ApplicationContextAwareProcessor注入的Aware

bean的生命周期.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享