SpringBean的生命周期

概要

bean生命周期:从对象的创建到销毁的过程,经历很多过程,总体可以分为下面几个步骤:

  • 实例化bean
  • 属性赋值
  • 初始化bean
  • 生存期
  • 销毁

一、bean的生命周期

Spring启动后,首先查找并加载我们配置的bean信息,以 BeanDefinition 对象缓存在 beanFactory 中。 然后,执行 beanFactory 中的 getBean 方法开始实例化bean,此时已经进入bean的生命历程。

1、实例化bean

方法:createBeanInstance()

启动Spring查找并加载被Spring管理的bean进行Bean的实例化,bean的实例化通过有两种方式:

  • java反射
  • cglib 字节码创建

2、属性赋值

方法:populateBean()

实例化后的对象bean被封装在BeanWrapper对象中,仅是对bean开辟了内存空间,整个对象仍然是一个原生的状态,并没有进行依赖注入。

依赖注入属性值这里分为两种情况:

  • 基本数据类型注入:需要从beanDefinition中获取属性值,然后填充即可,
  • 依赖对象注入:需要根据autowire类型处理(autowireByType、autowireByName), 但最终执行 getBean 方法获取这个对象后才可赋值,

这里有可能出现循环依赖的现象,spring是如何解决循环依赖的?(本章节不做说明)

3、初始化bean

方法:initializeBean()

bean实例化填充属性值完成后,便开始执行bean初始化动作,整个流程步骤如下:

  • 处理实现Aware接口
  • BeanPostProcessor#before
  • InitializingBean
  • 自定义init-method
  • BeanPostProcessor#after

3.1、处理实现Aware接口

invokeAwareMethods方法只处理:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware赋值;

关于 ApplicationContextAwareProcessor 后置处理器处理了: EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、 MessageSourceAware、ApplicationContextAware

3.2、BeanPostProcessor

当经过上述几个步骤后,bean对象已经被正确构造,但如果你想要对象被使用前再进行一些自定义的处理,就可以通过BeanPostProcessor接口实现;

该接口提供了两个函数:

  • postProcessBeforeInitialization: 传递当前正在初始化的bean对象,扩展bean任何前置动作。 这个函数会先于InitializingBean前执行,因此称为前置处理。 所有Aware接口的注入就是在这一步完成的。

  • postProcessAfterInitialization: 传递当前正在初始化的bean对象,扩展bean任何后置动作。 这个函数会在InitializingBean完成后执行,因此称为后置处理。 BeanPostProcessor后置处理器是AOP实现的关键(关键子类AnnotationAwareAspectJAutoProxyCreator)。

3.3、InitializingBean

当BeanPostProcessor的前置处理完成后就会进入本阶段。 InitializingBean接口只有一个函数:

  • afterPropertiesSet()

这一阶段也可以在bean正式构造完成前增加我们自定义的逻辑,但它与前置处理不同,由于该函数并不会把当前bean对象传进来, 因此在这一步没办法处理对象本身,只能增加一些额外的逻辑。

若要使用它,我们需要让bean实现该接口,并把要增加的逻辑写在该函数中。 然后Spring会在前置处理完成后检测当前bean是否实现了该接口,并执行afterPropertiesSet函数。 当然,Spring为了降低对客户代码的侵入性,给bean的配置提供了init-method属性,该属性指定了在这一阶段需要执行的函数名。 Spring便会在初始化阶段执行我们设置的函数。init-method本质上仍然使用了InitializingBean接口。

3.4、自定义init-method

通过元素的init-method属性指定初始化。

3.5、补充执行顺序

需要补充「执行顺序」是 PostConstruct,补充后的顺序是:

  • BeanPostProcessor#before
  • @PostConstruct
  • 实现了InitializingBean接口
  • init-method方法
  • BeanPostProcessor#after

注解@PostConstruct是如何解析执行的?

首先,在实例化bean后,填充属性之前,还有一个关键处理逻辑合并BeanDefinition,通过执行MergedBeanDefinitionPostProcessor中方法 postProcessMergedBeanDefinition()完善beanDefinition一些注解信息,例如:

  • CommonAnnotationBeanPostProcessor:用于解析注解@PostConstruct、@PreDestroy、@Resource,完善至RootBeanDefinition对象这些属性中, 分别是:externallyManagedInitMethods、externallyManagedDestroyMethods、externallyManagedConfigMembers;

  • AutowiredAnnotationBeanPostProcessor:用于解析注解@Autowired、@Value、@Inject,完善至RootBeanDefinition对象的 externallyManagedConfigMembers之中。

上面两个BeanPostProcessor,在执行时根据class.getSuperClass()向上循环获取这些注解信息,父类如果存在同样注解信息, 也写入RootBeanDefinition。

其次,既然解析@PostConstruct是通过BeanPostProcessor处理的,因此执行@PostConstruct注解方法也是通过BeanPostProcessor#before处理的, 这里使用的类InitDestroyAnnotationBeanPostProcessor(CommonAnnotationBeanPostProcessor继承的父类)执行,代码如下:

public class InitDestroyAnnotationBeanPostProcessor
		implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
  
    @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
    try {
      metadata.invokeInitMethods(bean, beanName);
    }
    catch (InvocationTargetException ex) {
      throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
    }
    catch (Throwable ex) {
      throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
    }
    return bean;
  }
  
  private class LifecycleMetadata {
    public void invokeInitMethods(Object target, String beanName) throws Throwable {
      Collection<LifecycleElement> checkedInitMethods = this.checkedInitMethods;
      Collection<LifecycleElement> initMethodsToIterate =
              (checkedInitMethods != null ? checkedInitMethods : this.initMethods);
      if (!initMethodsToIterate.isEmpty()) {
        for (LifecycleElement element : initMethodsToIterate) {
          if (logger.isTraceEnabled()) {
            logger.trace("Invoking init method on bean '" + beanName + "': " + element.getMethod());
          }
          // 反射调用
          element.invoke(target);
        }
      }
    }
  }
}

4、生存期

本质上就是对bean的调用、执行过程。

5、销毁

  • 通过实现DisposableBean接口的destroy()方法执行销毁;

  • 通过元素destroy-method属性指定销毁;

  • 或者在指定方法上加上@PreDestroy注解方式执行销毁。

实际使用过程中选择一种实现方式即可。

二、Bean 的生命周期验证

在这里,我们创建一个bean对象,根据spring bean的实例化流程,通过打印的方式就可以看到bean的生命周期执行情况了。

创建一个Bean对象

public class BeanLife implements InitializingBean, BeanNameAware { 
    public BeanLife() {
		System.out.println("LifeBeanTest invoke newInstance() ......");
	}
    @PostConstruct
    public void postConstruct(){
        System.out.println("LifeBeanTest invoke postConstruct() ......");
    }

    @PreDestroy
    public void preDestroy(){
        System.out.println("LifeBeanTest invoke preDestroy() ......");
    }
	
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("LifeBeanTest invoke afterPropertiesSet() ......");
	}
	@Override
	public void setBeanName(String name) {
		System.out.println("LifeBeanTest invoke BeanNameAware.setBeanName() ......");
	}
	public void getName() {
		System.out.println("LifeBeanTest invoke getName() ......");
	}
    public void initMethod() {
        System.out.println("LifeBeanTest invoke initMethod() ......");
    }
    public void destroy() {
        System.out.println("LifeBeanTest invoke destroy() ......");
    }
}

创建一个后置处理器

public class LifeBeanPostProcessor implements BeanPostProcessor {
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("LifeBeanTest invoke postProcessBeforeInitialization() ......");
		return bean;
	}
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("LifeBeanTest invoke postProcessAfterInitialization() ......");
		return bean;
	}
}

下面启动项目

@Configuration
public class AnnotationBeanRunner {

  @Bean
  public LifeBeanPostProcessor lifeBeanPostProcessor(){
    return new LifeBeanPostProcessor();
  }

  @Bean(initMethod = "initMethod", destroyMethod = "destroy")
  public BeanLife beanLife(){
    return new BeanLife();
  }

  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.scan("com.spring.debug.beans");
    context.refresh();
    BeanLife bean = context.getBean(BeanLife.class);
    bean.getName();
  }
}

启动之后,打印信息如下

LifeBeanTest invoke newInstance() ......
LifeBeanTest invoke BeanNameAware.setBeanName() ......
LifeBeanTest invoke postProcessBeforeInitialization() ......
LifeBeanTest invoke postConstruct() ......
LifeBeanTest invoke afterPropertiesSet() ......
LifeBeanTest invoke initMethod() ......
LifeBeanTest invoke postProcessAfterInitialization() ......
LifeBeanTest invoke preDestroy() ......
LifeBeanTest invoke destroy() ......

三、Bean生命周期的源码

从上述打印结果中看到了bean的生命周期执行流程,下面我们回到spring 源码中可以看到类 BeanFactory,有这样一段注释:

/**
 * The root interface for accessing a Spring bean container.

 * <p>Bean factory implementations should support the standard bean lifecycle interfaces
 * as far as possible. The full set of initialization methods and their standard order is:
 * <ol>
 * <li>BeanNameAware's {@code setBeanName}
 * <li>BeanClassLoaderAware's {@code setBeanClassLoader}
 * <li>BeanFactoryAware's {@code setBeanFactory}
 * <li>EnvironmentAware's {@code setEnvironment}
 * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
 * <li>ResourceLoaderAware's {@code setResourceLoader}
 * (only applicable when running in an application context)
 * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
 * (only applicable when running in an application context)
 * <li>MessageSourceAware's {@code setMessageSource}
 * (only applicable when running in an application context)
 * <li>ApplicationContextAware's {@code setApplicationContext}
 * (only applicable when running in an application context)
 * <li>ServletContextAware's {@code setServletContext}
 * (only applicable when running in a web application context)
 * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
 * <li>InitializingBean's {@code afterPropertiesSet}
 * <li>a custom init-method definition
 * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
 * </ol>
 *
 * <p>On shutdown of a bean factory, the following lifecycle methods apply:
 * <ol>
 * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
 * <li>DisposableBean's {@code destroy}
 * <li>a custom destroy-method definition
 * </ol>
 *
 */
public interface BeanFactory {
    /**
     * Return an instance, which may be shared or independent, of the specified bean.
     * <p>This method allows a Spring BeanFactory to be used as a replacement for the
     * Singleton or Prototype design pattern. Callers may retain references to
     * returned objects in the case of Singleton beans.
     * <p>Translates aliases back to the corresponding canonical bean name.
     * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
     * @param name the name of the bean to retrieve
     * @return an instance of the bean
     * @throws NoSuchBeanDefinitionException if there is no bean with the specified name
     * @throws BeansException if the bean could not be obtained
     */
    Object getBean(String name) throws BeansException;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值