The Spring BeanPostProcessor interface uses a detailed explanation

  • 2020-12-13 18:57:34
  • OfStack

Spring provides a number of PostProcessor extensions for developers, such as BeanPostProcessor, BeanFactoryPostProcessor, BeanValidationPostProcessor and other series 1 post-processor extensions. Most of their usage patterns are similar. Learn one of them and master his usage pattern. The others can be explained by analogy.

Here, BeanPostProcessor is used as an example to show how it is used.

The BeanPostProcessor interface provides two methods for developers to customize: postProcessBeforeInitialization and postProcessAfterInitialization.

postProcessBeforeInitialization: This method is mainly for the custom processing of spring before calling the initialization method on bean initialization.

postProcessAfterInitialization: This method focuses on custom processing for spring after calling the initialization method on bean initialization.

Sample code:


/**
 *  test bean
 */
public class Cat {
  private String name;
  private int age;
  public void say() {
    System.out.println("name:" + name);
    System.out.println("age:" + age);
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
}

/**
 *  Custom post processor 
 */
public class CatBeanPostProcessor implements BeanPostProcessor {

  @Nullable
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof Cat) {
      // Output the original property 
      Cat cat = (Cat) bean;
      cat.say();
      return bean;
    }
    return bean;
  }

  @Nullable
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof Cat) {
      // Modify the property value and return 
      Cat cat = (Cat) bean;
      cat.setName("hello maomi");
      cat.setAge(3);
      return cat;
    }
    return bean;
  }
}

/**
 *  run 
 */
public class Run {
  public static void main(String[] args) {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml");
    Cat cat = (Cat) applicationContext.getBean("cat");
    cat.say();
  }
}

xml configuration information


  <!-- configuration bean And initialize -->
  <bean id="cat" class="com.source.postprocessor.Cat" >
    <property name="name" value="HelloKitty" />
    <property name="age" value="1" />
  </bean>

  <bean id="catBeanPostProcessor" class="com.source.postprocessor.CatBeanPostProcessor" />

Output results:

name:HelloKitty
age:1
name:hello maomi
age:3

You can see that the bean information that has been processed by the post-processor has changed. Finally, take a look at how the custom implementation is invoked in the source code.

In initializing the bean method: ES52en.java


  /**
  *  Initialize the bean
  */
 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
   // Omit irrelevant code 
   Object wrappedBean = bean;
   // Initialize the former 
   if (mbd == null || !mbd.isSynthetic()) {
     wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   }

   try {
     // Call initialization method initialization bean
     invokeInitMethods(beanName, wrappedBean, mbd);
   }
   catch (Throwable ex) {
     throw new BeanCreationException(
         (mbd != null ? mbd.getResourceDescription() : null),
         beanName, "Invocation of init method failed", ex);
   }
   // After the initialization 
   if (mbd == null || !mbd.isSynthetic()) {
     wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   }
   return wrappedBean;
 }
 //postProcessBeforeInitialization The method call 
 @Override
 public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
     throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
     // Call customization postProcessBeforeInitialization methods 
     Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
     if (current == null) {
       return result;
     }
     result = current;
   }
   return result;
 }
 //postProcessAfterInitialization The method call 
 @Override
 public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
     throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
     // The custom postProcessAfterInitialization The method call 
     Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
     if (current == null) {
       return result;
     }
     result = current;
   }
   return result;
 }

Related articles: