前言:
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;
}