Spring中的生命周期

1. 简介

本文带大家整体掌握下Spring中的Bean生命周期,让你大大提升Spring内功。学会本文,让你在解决Spring中相关问题的时候不会再出现无从下手的问题。大家一定要收藏记忆,面试也会被经经常问到。本文内容比较简单粗暴,只讲重点,建议大家后续按照文中要点看下源码,了解一下细节,顺便学习下Spring的设计思想。

2. 全局俯视生命周期 Aware、PostProcessor

这里首先介绍两个词 Aware 、PostProcessor ,Spring整个生命周期的控制都在围绕着这两个词展开,如

  • BeanPostProcessor:Spring 中Bean对象的生命周期管理处理器,后面讲到的Bean每个参与环节生命周期管理的处理器都是实现了这个接口
  • BeanFactoryPostProcessor:Spring 中 BeanFactory的生命周期管理器接口
  • BeanNameAware 接口:当给Bean对象设置名字时会被这个接口感知到,调用接口里setBeanName()的方法
    其他的这里不再列举,后面会详细介绍

3. 第一阶段: 元信息配置、解析、注册、合并阶段

3.1 第一阶段介绍

  • 配置
    在Spring 中通过 xml配置文件的标签 或者注解配置 @Bean、@Compontent标注的类进行配置。

  • 解析
    Spring 通过XmlBeanDefinitionReaderAnnotatedBeanDefinitionReader 类把我们通过xml和注解方式配置的Bean会解析成一个BeanDefinition对象。BeanDefinition对象中定义了和Bean相关的信息,如Bean 的class、name、scop、parent(父类) 等待。

  • 注册
    DefaultListableBeanFactory 这个类 负责把定义好的BeanDefinition 注册到Spring 容器中

  • 合并
    在我们定义的类中有各种相互依赖继承关系,Spring会把 BeanDefinition 进行合并处理,最后得到一个RootBeanDefinition 对象,后面是使用这个类进行加载,实例化等操作。

下面来段小代码理解一下

@Test
public void test() {
    //使用BeanDefinitionBuilder 自定义一个 BeanDefinition 对象
    BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(Car.class.getName());
    //设置属性
    beanDefinitionBuilder.addPropertyValue("name", "法拉利");
    //获取BeanDefinition
    BeanDefinition carBeanDefinition = beanDefinitionBuilder.getBeanDefinition();
    System.out.println(carBeanDefinition);

    //创建spring容器
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); 
    //调用registerBeanDefinition向容器中注册bean
    factory.registerBeanDefinition("car", carBeanDefinition); 
    Car bean = factory.getBean("car", Car.class);
    System.out.println(bean);
}

3.2. 第一阶段扩展点

3.2.1. Spring工厂扩展一:Bean 注册接阶段

BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法会在Spring工厂注册阶段调用,注册阶段结束后Spring不会再对Bean进行注册,比如这个阶段我们可以自定义注册一些新的Bean,其他可干的事情看BeanDefinitionRegistry相关API

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

3.2.2. Spring工厂扩展二:BeanFactory后置处理

BeanFactoryPostProcessor#postProcessBeanFactory方法会在Spring工厂注册阶段结束后调用,可以对BeanFactory进行一些扩展

@FunctionalInterface
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

4. 第二阶段:实例化阶段

先看代码片段

@Nullable
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }

在所有的Bean 实例化之前都会调用此方法,去遍历BeanPostProcessor,然后执行具体的实现方法。 在Spring 中有很多类似结构的代码片段,在不同环节遍历执行不同类型的PostProcesser。所以我们要参与Bean生命周期管理,只需要实现对应类型的BeanPostProcessor接口即可,这里我按照实际执行顺序梳理一个清单出来,感兴趣可以看下源码。

4.1 实例化阶段

1.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 方法,如果此方法返回当前Bean实例,将跳过Spring自带后续的实例化过程。

default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}
  1. SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors返回一个构造器,这个构造器在new 对象时使用,如果返回null ,使用默认构造器
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
throws BeansException {
    return null;
}
  1. MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition 方法,我们可以在这个方法内部对合并之后的BeanDefinition进行再次处理。
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

它有两个实现类:

  • org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
    在 postProcessMergedBeanDefinition 方法中对 @Autowired、@Value 标注的方法、字段进行缓存
  • org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
    在 postProcessMergedBeanDefinition 方法中对 @Resource 标注的字段、@Resource 标注的方法、 @PostConstruct 标注的字段、 @PreDestroy标注的方法进行缓存
  1. InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation,对象创建完成之后调用,当这个方法返回false,后续的Bean 属性赋值都会被跳过。
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    return true;
}

4.2 属性赋值阶段

  1. InstantiationAwareBeanPostProcessor#postProcessProperties 属性赋值前会调用。
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
    throws BeansException {

    return null;
}

看下调用逻辑

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
        if (pvsToUse == null) {
            if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                return;
            }
        }
        pvs = pvsToUse;
    }
}

从调用逻辑可以看出,如果InstantiationAwareBeanPostProcessor中的postProcessPropertiespostProcessPropertyValues都返回空的时候,表示这个bean不需要设置属性,直接返回了,直接进入下一个阶段。PropertyValues中保存了bean实例对象中所有属性值的设置,所以我们可以在这个这个方法中对PropertyValues值进行修改。

两个重要实现类

  • AutowiredAnnotationBeanPostProcessor在这个方法中对@Autowired、@Value标注的字段、方法注入值。
  • CommonAnnotationBeanPostProcessor在这个方法中对@Resource标注的字段和方法注入值。

4.3 Bean Aware 接口回调

  1. 如果我们的bean实例实现了下面面的这些Aware接口, 将会按照执行顺序把 bean名称、BeanClassLoader、BeanFactory都注入进去。
private void invokeAwareMethods(final String beanName, final Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }

2.ApplicationContextAwareProcessor#postProcessBeforeInitialization中会依次调用下面接口中的方法,将Aware前缀对应的对象注入到bean实例中。

  • EnvironmentAware:注入Environment对象
  • EmbeddedValueResolverAware:注入EmbeddedValueResolver对象
  • ResourceLoaderAware:注入ResourceLoader对象
  • ApplicationEventPublisherAware:注入ApplicationEventPublisher对象
  • MessageSourceAware:注入MessageSource对象
  • ApplicationContextAware:注入ApplicationContext对象

4.4 初始化

  1. CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization中会调用bean中所有标注@PostConstruct注解的方法
  2. 调用InitializingBean接口的afterPropertiesSet方法
  3. 调用定义bean的时候指定的初始化方法,如@Bean(initMethod = "初始化的方法")
  4. 轮询我们自定义实现的BeanPostProcessor#postProcessAfterInitialization方法,当返回null的时候,会中断轮询操作。

5. 实例化完成

容器中所有非延迟加载的单例Bean初始化完成后容器会调用SmartInitializingSingleton#afterSingletonsInstantiated
方法。
本方法调用结束后,容器中的Bean就可以使用了。

6. 销毁阶段

Bean 的销毁会依次调用以下

  1. 轮询轮询BeanPostProcessors 列表,调用 DestructionAwareBeanPostProcessor#postProcessBeforeDestruction
  2. CommonAnnotationBeanPostProcessor#postProcessBeforeDestruction 处理 @PreDestroy标注的方法
  3. 如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中的destroy方法
  4. 调用bean自定义的销毁方法,如@Bean(destroyMethod = "销毁方法")

7.小结

  1. 很多生命周期环节都是在轮询 BeanPostProcessors列表,调用其对应方法,所以想要参与Bean的生命周期,只要写一个类实现对应生命周期的BeanPostProcessors就可以
  2. 补充一个知识@Order 注解 和 Order 接口 可以指定在轮询BeanPostProcessors列表时的执行顺序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值