Spring bean核心生命周期

Spring bean生命周期

前言

在Spring 框架中,代码定义的对象统一由Spring 容器管理,由Spring容器来创建,初始化。

那么一个bean的简版生命周期如下图:

图一

实例化一个bean对象,完成属性注入,执行初始化方法,此时bean可以被我们所使用,最后销毁。

Spring也赋予了一个bean在上述4个阶段中做一些增强的操作,下文详细分析。

Spring bean生命周期

Spring bean详细生命周期流程图:

图二

从doCreateBean() 方法开始

AbstractAutowireCapableBeanFactory抽象类:

省略部分代码
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
   throws BeanCreationException {

  // Instantiate the bean.
  BeanWrapper instanceWrapper = null;
  if (mbd.isSingleton()) {
   instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  }
  if (instanceWrapper == null) {
      //实例化
   instanceWrapper = createBeanInstance(beanName, mbd, args);
  }
  Object bean = instanceWrapper.getWrappedInstance();

  // Initialize the bean instance.
  Object exposedObject = bean;
    //属性填充
    populateBean(beanName, mbd, instanceWrapper);
    //初始化bean实例
    exposedObject = initializeBean(beanName, exposedObject, mbd);

  return exposedObject;
 }

在doCreateBean()方法中:

  • 调用createBeanInstance() 方法完成对象实例化。

  • 调用populateBean() 方法填充属性。

  • 调用initializeBean() 方法完成bean实例的初始化方法回调。

initializeBean()方法

AbstractAutowireCapableBeanFactory抽象类:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
  if (System.getSecurityManager() != null) {
   AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    invokeAwareMethods(beanName, bean);
    return null;
   }, getAccessControlContext());
  }
  else {
      //调用感知方法
   invokeAwareMethods(beanName, bean);
  }

  Object wrappedBean = bean;
  if (mbd == null || !mbd.isSynthetic()) {
      //初始化前调用bean后置处理器
   wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  }

  try {
      //调用初始化方法
   invokeInitMethods(beanName, wrappedBean, mbd);
  }
  catch (Throwable ex) {
   throw new BeanCreationException(
     (mbd != null ? mbd.getResourceDescription() : null),
     beanName, "Invocation of init method failed", ex);
  }
  if (mbd == null || !mbd.isSynthetic()) {
      //初始化后调用bean后置处理器
   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  }

  return wrappedBean;
 }

在initializeBean()方法中:

  • 调用invokeAwareMethods() 方法完成相关属性的注入。

  • 初始化前调用bean后置处理器。

  • 调用invokeInitMethods() 方法完成InitializingBean接口的回调。

  • 初始化后调用bean后置处理器。

invokeAwareMethods() 方法注入相关属性

private void invokeAwareMethods(String beanName, 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);
   }
  }
 }

applyBeanPostProcessorsBeforeInitialization()
applyBeanPostProcessorsAfterInitialization()
方法中会获取bean后置处理器集合,依次执行:

  • ApplicationContextAwareProcessor 后置处理器:用于注入应用上下文属性。

  • InitDestroyAnnotationBeanPostProcessor 后置处理器:会找出@PostConstruct、@PreDestroy修饰的方法并执行。

自定义init方法

图二中调用自定义init方法invokeCustomInitMethod() 是指:

  • 在xml配置bean时通过init-method标签指定。

  • 或者通过注解@Bean(initMethod = "xxx")指定,默认为空。

验证

@Component
@Slf4j
@Scope(value = "prototype")
@PropertySource({"classpath:bootstrap.yml"})
public class FullBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean,
        InstantiationAwareBeanPostProcessor,
        BeanPostProcessor,
        DisposableBean {

    private String name;

    public FullBean() {
        log.info("无参构造方法: {}", this);
    }

    @Value("${name}")
    public void setName(String name) {
        log.info("setName: {}", name);
        this.name = name;
    }

    @Override
    public void setBeanName(String name) {
        log.info("beanName: {}", name);
    }
    
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        log.info("beanFactory: {}", beanFactory.getClass());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("applicationContext: {}", applicationContext.getId());
    }

    @PostConstruct
    public void postConstruct() {
        log.info("postConstruct执行");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("afterPropertiesSet执行");
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        log.info("实例化前: {}", beanName);
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        log.info("实例化后: {}", beanName);
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        log.info("后处理属性注入: {}", beanName);
        return null;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        log.info("属性注入: {}", beanName);
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        log.info("初始化前: {}", beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        log.info("初始化后: {}", beanName);
        return bean;
    }

    @Override
    public void destroy() throws Exception {
        log.info("bean销毁");
    }
}

执行结果:

实现BeanPostProcessor接口不生效原因

单例模式下:

bean作用域默认为单例,也可以在bean上加 @Scope(value = "singleton")。 此时FullBean类中不会执行BeanPostProcessor接口覆盖的方法。

原因:

AbstractApplicationContext#refresh() -> registerBeanPostProcessors() 方法中,FullBean由于实现了BeanPostProcessor接口,会被提前初始化,此时FullBean还未注册到BeanPostProcessor集合中。

refresh()方法分析见:Spring boot启动流程分析精简版

registerBeanPostProcessors() 方法会调用 PostProcessorRegistrationDelegate#registerBeanPostProcessors()

由于fullBean 是一个后置处理器类,那么此时fullBean 会先被创建,并放入单例缓存池中(缓存在DefaultSingletonBeanRegistry 类的singletonObjects 属性 map集合中),接着会将此bean注册到BeanPostProcessor 集合中。所以在单例情况下,实现了BeanPostProcessor 接口后,不会执行其实现的方法。

后面 getBean("fullBean") 直接从缓存中获取bean 实例。

原型模式下:

在类上注解@Scope(value = "prototype") 设置此bean作用域为原型模式。容器启动时由于fullBean 是后置处理器类,也不会执行。

Spring 应用容器启动完毕后,下一次getBean("fullBean") 时,会再次创建bean对象,此时会执行其后置处理器覆盖的方法。

小结

本文分析了核心的关键流程,旨在了解bean 的生命周期。建议对照图二的流程图,去debug 源码会更加清晰。

注:类初始化和bean生命周期中的初始化不是一个概念

  • 类初始化:Class.forName() 过程叫类初始化,会执行static block。返回一个class对象的引用。

  • 文中bean初始化:执行对应的初始化方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值