• (一)前言
  • (二)Spring中对bean的初始化处理
  • (三)Spring有4种定义初始化(销毁同理)的方法:
  • 一、在initializeBean()中进行方法调用
  • 1、用注解@Bean(initMethod=”init”)
  • 2、 bean实现InitializingBean 和 DisposableBean接口
  • 二、通过后置处理器
  • 1、 使用@PostConstruct(销毁:@Predestory)
  • 2、自定义后置处理器实现BeanFactoryProcessor接口
  • (四)结语


(一)前言

本篇文章是Spring学习的一个入门阶段,详细介绍了Spring的Bean生命周期中初始化方法的种类,引入了Spring的后置处理器概念。

(二)Spring中对bean的初始化处理

Spring在beanFactory中的doCreatBean()中的进行初始化的一系列操作都会在该方法中进行:

/**对bean做初始化处理,在这里会执行一些后置处理器(postProcessors)*/
exposedObject = initializeBean(beanName,exposedObject, mbd);

(三)Spring有4种定义初始化(销毁同理)的方法:

一、在initializeBean()中进行方法调用

1、用注解@Bean(initMethod=”init”)

@Configurable
public class Appconfig {
   @Bean(value = "a",initMethod = "init",destroyMethod = "destroy")
   public A a(){
      return new A();
   }
} 
public class A{
   public A(){
      System.out.println("create A");
   }
   public void init(){
      System.out.println("init A");
   }
   public void destroy(){
      System.out.println("destroy A");
   }
}

2、 bean实现InitializingBean 和 DisposableBean接口

public class A implements InitializingBean {
   public A(){
      System.out.println("create A");
   }
   @Override
   public void afterPropertiesSet() throws Exception {
      System.out.println("init A by InitializingBean");
   }
}

以上两种方法在initializeBean()方法中调用,称为生命周期初始化回调方法,但实现的方式不同,1是通过反射调用init()方法,2是通过实例化的bean直接调用afterPropertiesSet(),且先调用afterPropertiesSet(),后调用init(),测试如下图:

SpringTemplateEngine初始化加载慢 spring初始化代码_spring


从Spring源码中可以知道invokeInitMethod()方法内先使用bean直接调用afterPropertiesSet(),然后通过反射invoke用户在@Bean中自定义的init()。

SpringTemplateEngine初始化加载慢 spring初始化代码_初始化_02

二、通过后置处理器

由于该类型方法使用效果与第一类型相似,经常会被人弄混。严格意义上来说,通过后置处理器执行是在初始化之前的applyBeanPostProcessorsBeforeInitialization()方法中,应该称为生命周期初始化之前回调方法。Spring源码如下:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessBeforeInitialization(result,beanName);
      if(current == null) return result;
      result = current;
   }
   return result;
}

1、 使用@PostConstruct(销毁:@Predestory)

@Component
public class A {
   public A() { System.out.println("create A");}
   @PostConstruct
   public void initByPostConstruce(){
      System.out.println("inti by PostConstruct");
   }
}

@PostConstruct 会由CommonAnnotationBeanPostProcessor后置处理器进行解析,由于该类继承了InitDestroyAnnotationBeanPostProcessor,因此会调用父类的postProcessBeforeInitialization(result,beanName)方法,然后通过反射执行@PostConstruct所注解的方法。后置处理器代码片段:

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
   LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
   try {
      metadata.invokeInitMethods(bean, beanName);
   }
   return bean;
}

2、自定义后置处理器实现BeanFactoryProcessor接口

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("init by BeanPostProcessor");
      return bean;
   }
}

该后置处理器是在applyBeanPostProcessorsBeforeInitialization()中的for循环执行自定义的beanPostProcessor. postProcessBeforeInitialization()方法。

总结:

SpringTemplateEngine初始化加载慢 spring初始化代码_java_03

(四)结语

Spring的强大在于:Spring在bean的整个生命周期中一共九次调用后置处理器对bean进行增强,同时Spring中包含各种内置处理器可以对bean进行不同的操作(例:Spring的AOP和TransactionManager都是基于此实现的)。

Spring官方文档:https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core