4、Mini-spring BeanFactoryPostProcessor和BeanPostProcessor

255 阅读4分钟

前言:

BeanFactoryPostProcessor和BeanPostProcessor是Spring框架中具有重要级地位的两个接口,理解了这两个接口的作用,基本就理解Spring的核心原理了。

BeanFactoryPostProcessor:

BeanFactoryPostProcessor是Spring提供的容器扩展机制,允许我们在bean实例化之前修改bean的定义信息即BeanDefinition的信息。其重要的实现类有ProPertyPlaceholderConfigurer和CustomEditorConfigurer.

ProPertyPlaceholderConfigurer见名知意,是属性占位符配置,实际上这个类就是将properties文件的配置值替换xml文件中的占位符。PS:这个类在5.2后被标注过时,现在官方推荐使用,PropertySourcesPlaceholderConfigurer。但是作用是类似的。CustomerEditorConfigurer的作用是实现类型转换。

BeanPostProcessor:

BeanPostProcessor也是Spring提供的容器扩展机制,不同于BeanFactoryPostProcessor的是,BeanPostProcessor在bean实例化后修改bean或替换bean。也就是在BeanDefinition实例化之后再对bean的信息修改。BeanPostProcessor是SpringAOP实现的关键。

具体实现:

1、BeanFactoryPostProcessor

/**
 * 允许自定义修改BeanDefinition的属性值
 */
public interface BeanFactoryPostProcessor {
   /**
    * 在所有BeanDefintion加载完成后,但在bean实例化之前,提供修改BeanDefinition属性值的机制
    */
   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

   @Override
   public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
      BeanDefinition personBeanDefiniton = beanFactory.getBeanDefinition("person");
      PropertyValues propertyValues = personBeanDefiniton.getPropertyValues();
      //将person的name属性改为ivy
      propertyValues.addPropertyValue(new PropertyValue("name", "ivy"));
   }
}

测试:

可以看到,BeanFactoryPostProcessor中提供了postProcessBeanFacoty()的方法,方法的参数是将我们构造好的beanFactory传递进去,然后通过该方法的具体实现修改beanFactory中BeanDefinition的属性,此时bean还没有被实例化,我们直接将beanDefinition进行了修改,下面的代码是进行具体的测试。

@Test
public void testBeanFactoryPostProcessor() throws Exception {
   DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
   beanDefinitionReader.loadBeanDefinitions("classpath:spring.xml");

   //在所有BeanDefintion加载完成后,但在bean实例化之前,修改BeanDefinition的属性值
   CustomBeanFactoryPostProcessor beanFactoryPostProcessor = new CustomBeanFactoryPostProcessor();
   beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);

   Person person = (Person) beanFactory.getBean("person");
   System.out.println(person);
   //name属性在CustomBeanFactoryPostProcessor中被修改为ivy
   assertThat(person.getName()).isEqualTo("ivy");
}

2、BeanPostProcessor

BeanPostProcessor提供了两个方法,传入bean对象,以及beanName。分别在bean初始化之前执行和bean初始化之后执行。

/**
 * 用于修改实例化后的bean的修改扩展点
 */
public interface BeanPostProcessor {

   /**
    * 在bean执行初始化方法之前执行此方法
    *
    * @param bean
    * @param beanName
    * @return
    * @throws BeansException
    */
   Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

   /**
    * 在bean执行初始化方法之后执行此方法
    *
    * @param bean
    * @param beanName
    * @return
    * @throws BeansException
    */
   Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
public class CustomerBeanPostProcessor implements BeanPostProcessor {
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("CustomerBeanPostProcessor#postProcessBeforeInitialization");
      //换兰博基尼
      if ("car".equals(beanName)) {
         ((Car) bean).setBrand("lamborghini");
      }
      return bean;
   }

   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("CustomerBeanPostProcessor#postProcessAfterInitialization");
      return bean;
   }
}

测试:

可以看到,相较于BeanFactoryPostProcessor那种直接将beanFactory作为参数,然后通过自身的方法修改BeanDefinition信息的方式,BeanPostProcess是先实例化自身,然后将自身实例化后的处理器添加到beanFactory中。前面我们提到BeanPostProcessor是在bean实例化之后修改bean对应的信息的。我们继续看真正实现修改的地方,其实就是getBean方法。

@Test
public void testBeanPostProcessor() throws Exception {
   DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
   XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
   beanDefinitionReader.loadBeanDefinitions("classpath:spring.xml");

   //添加bean实例化后的处理器
   CustomerBeanPostProcessor customerBeanPostProcessor = new CustomerBeanPostProcessor();
   beanFactory.addBeanPostProcessor(customerBeanPostProcessor);

   Car car = (Car) beanFactory.getBean("car");
   System.out.println(car);
   //brand属性在CustomerBeanPostProcessor中被修改为lamborghini
   assertThat(car.getBrand()).isEqualTo("lamborghini");
}

我们重点看initializeBean方法,这个方法就是在bean实例化后进行前置后置处理。

protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
   Object bean = null;
   try {
      bean = createBeanInstance(beanDefinition);
      //为bean填充属性
      applyPropertyValues(beanName, bean, beanDefinition);
      //执行bean的初始化方法和BeanPostProcessor的前置和后置处理方法
      bean = initializeBean(beanName, bean, beanDefinition);
   } catch (Exception e) {
      throw new BeansException("Instantiation of bean failed", e);
   }

   addSingleton(beanName, bean);
   return bean;
}

可以看到initializeBean方法分三步,先是执行BeanPostProcessor的前置处理,然后执行bean的初始化方法,最后再执行BeanPostProcessor的后置方法。我们先不去看bean的初始化。

在执行BeanPostProcessor的前置和后置处理方法的时候,调用的是applyBeanPostProcessorsBeforeInitialization(bean, beanName)applyBeanPostProcessorsAfterInitialization(bean, beanName),这两个方法来自该抽象类继承的接口AutowireCapableBeanFactory自动装配工厂,这个类里面的两个方法用来执行BeanPostProcessor。(为了方便学习,在前面作者对整体的类结构做了些小小的调整,尽量和spring中的保持一致)

applyBeanPostProcessorsBeforeInitialization()applyBeanPostProcessorsAfterInitialization()两个方法内部也很清晰,就是去获取我们所有放置的BeanPostProcessor,然后去调用对应的处理方法,返回对应的bean。所以总结起来就是BeanPostProcessor是在bean实例化后,执行postProcessBeforeInitialization()初始化前方法,然后bean初始化后再执行postProcessAfterInitialization()后方法。

protected Object initializeBean(String beanName, Object bean, BeanDefinition beanDefinition) {
   //执行BeanPostProcessor的前置处理
   Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);

   //TODO 后面会在此处执行bean的初始化方法
   invokeInitMethods(beanName, wrappedBean, beanDefinition);

   //执行BeanPostProcessor的后置处理
   wrappedBean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
   return wrappedBean;
}

@Override
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;
}

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}