spring BeanPostProcessor 生命週期

  BeanPostProcessor:後置處理器

  spring使用模板模式,在bean的創建過程中安插了許多錨點,用戶尋找對應的錨點,通過重寫方法介入到bean的創建過程當中。本節通過重寫這些錨點,學習如何使用BeanPostProcessor、獲取各類BeanAware並且理清bean的生命週期

  代碼

  控制檯

  // 控制檯的輸出結果

  1. postProcessBeforeInstantiation被調用

  2. 構造方法被調用,name:小小

  3. postProcessAfterInstantiation被調用

  4. postProcessProperties被調用

  5. BeanNameAware被調用, 獲取到的beanName:lifeCycleBean

  6. BeanFactoryAware被調用,獲取到beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@117e949d: defining beans [lifeCycleBean,lifeCycleBeanPostProcessor]; root of factory hierarchy

  7. ApplicationContextAware被調用,獲取到ApplicationContextAware:org.springframework.context.support.ClassPathXmlApplicationContext@71e9ddb4, started on Sat Feb 22 20:30:35 CST 2020

  8. postProcessBeforeInitialization被調用,把name改成中中

  9. afterPropertiesSet被調用

  10. myInit自定義初始化方法被調用,name:中中

  11. postProcessAfterInitialization被調用,把name改成大大

  12. bean創建完成 name: 大大

  13. DisposableBean被調用

  14. destroy-method自定義銷燬方法被調用

  Process finished with exit code 0

  創建類LifeCycleBean

  public class LifeCycleBean implements

  BeanNameAware,

  BeanFactoryAware,

  ApplicationContextAware,

  InitializingBean,

  DisposableBean {

  private BeanFactory beanFactory;

  private ApplicationContext applicationContext;

  private String name;

  public LifeCycleBean(String name) {

  System.out.println("2. 構造方法被調用,name:" + name);

  this.name = name;

  }

  @Override

  public void setBeanName(String name) {

  System.out.println("5. BeanNameAware被調用, 獲取到的beanName:" + name);

  }

  @Override

  public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

  this.beanFactory = beanFactory;

  System.out.println("6. BeanFactoryAware被調用,獲取到beanFactory:" + beanFactory);

  }

  @Override

  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

  this.applicationContext = applicationContext;

  System.out.println("7. ApplicationContextAware被調用,獲取到ApplicationContextAware:" + applicationContext);

  }

  @Override

  public void afterPropertiesSet() throws Exception {

  System.out.println("9. afterPropertiesSet被調用");

  }

  public void myInit() {

  System.out.println("10. myInit自定義初始化方法被調用,name:" + getName());

  }

  @Override

  public void destroy() throws Exception {

  System.out.println("13. DisposableBean被調用");

  }

  public void myDestroy() {

  System.out.println("14. destroy-method自定義銷燬方法被調用");

  }

  public String getName() {

  return name;

  }

  public void setName(String name) {

  this.name = name;

  }

  public BeanFactory getBeanFactory() {

  return beanFactory;

  }

  public ApplicationContext getApplicationContext() {

  return applicationContext;

  }

  }

  創建BeanPostProcessor後置處理器(postProcessProperties過時了,這裏就不演示了)

  public class LifeCycleBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

  @Override

  public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {

  if (beanName.equals("lifeCycleBean")) {

  System.out.println("1. postProcessBeforeInstantiation被調用");

  }

  return null;

  }

  @Override

  public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {

  if (beanName.equals("lifeCycleBean")) {

  System.out.println("3. postProcessAfterInstantiation被調用");

  }

  return true;

  }

  @Override

  public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {

  if (beanName.equals("lifeCycleBean")) {

  System.out.println("4. postProcessProperties被調用");

  }

  return null;

  }

  // @Override

  // public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

  // return pvs;

  // }

  @Override

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

  if (beanName.equals("lifeCycleBean")) {

  ((LifeCycleBean) bean).setName("中中");

  System.out.println("8. postProcessBeforeInitialization被調用,把name改成中中");

  }鄭州婦科醫院 http://www.120zzkd.com/

  return bean;

  }

  @Override

  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

  if (beanName.equals("lifeCycleBean")) {

  ((LifeCycleBean) bean).setName("大大");

  System.out.println("11. postProcessAfterInitialization被調用,把name改成大大");

  }

  return bean;

  }

  }

  xml配置文件

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

  xsi:schemaLocation="http://www.springframework.org/schema/beans

  http://www.springframework.org/schema/beans/spring-beans.xsd">

  destroy-method="myDestroy"

  init-method="myInit">

  測試類

  /**

  * @author: chaitou

  */

  public class LifeCycleTest {

  @Test

  public void test() {

  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("lifeCycle.xml");

  LifeCycleBean myLifeCycleBean = applicationContext.getBean("lifeCycleBean", LifeCycleBean.class);

  System.out.println("12. bean創建完成 name: " + myLifeCycleBean.getName());

  ((ClassPathXmlApplicationContext) applicationContext).destroy();

  }

  }

  結果

  // 控制檯的輸出結果

  1. postProcessBeforeInstantiation被調用

  2. 構造方法被調用,name:小小

  3. postProcessAfterInstantiation被調用

  4. postProcessProperties被調用

  5. BeanNameAware被調用, 獲取到的beanName:lifeCycleBean

  6. BeanFactoryAware被調用,獲取到beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@117e949d: defining beans [lifeCycleBean,lifeCycleBeanPostProcessor]; root of factory hierarchy

  7. ApplicationContextAware被調用,獲取到ApplicationContextAware:org.springframework.context.support.ClassPathXmlApplicationContext@71e9ddb4, started on Sat Feb 22 20:30:35 CST 2020

  8. postProcessBeforeInitialization被調用,把name改成中中

  9. afterPropertiesSet被調用

  10. myInit自定義初始化方法被調用,name:中中

  11. postProcessAfterInitialization被調用,把name改成大大

  12. bean創建完成 name: 大大

  13. DisposableBean被調用

  14. destroy-method自定義銷燬方法被調用

  Process finished with exit code 0

  分析總結

  BeanPostProcess

  實例化相關:postProcessBeforeInstantiation、postProcessAfterInstantiation

  填充屬性相關:postProcessProperties、postProcessPropertyValues(已過時沒有演示)

  初始化相關:postProcessBeforeInitialization、postProcessAfterInitialization

  通過重寫BeanPostProcess的方法,可以介入bean創建的不同環節。同時通過postProcessBeforeInitialization將bean的name屬性值從小小改成了中中,又通過postProcessAfterInitialization將中中改成了大大,成功介入了bean的創建,並且依據我們的意願修改了bean

  BeanNameAware、BeanFactoryAware、ApplicationContextAware

  這3類不屬於後置處理器的範疇,學名叫感知器,讓bean能感知到整個容器上下文信息的接口。spring在創建過程中,通過回調子類的setBeanName, setBeanFactory, setApplicationContext實現了BeanName, BeanFactory, ApplicationContext的注入,讓bean能夠感知獲取到spring上下文的相關信息。雖然實現的東西很牛逼,但是實現的原理一點不復雜。通過檢測當前的bean是否實現相關Aware,如果實現則調用子類set方法,將當前的BeanFactory等作爲參數傳入,直接上源碼,看不懂可以參考這篇源碼:(https://blog.csdn.net/chaitoudaren/article/details/104833613)

  spring源碼17: 初始化

  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);

  }

  }

  }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章