PostProcessor:后处理器;
BeanPostProcessor:Bean的后处理器(处理的对象是bean)
(1)看一下BeanPostProcessor接口的源码:
public interface BeanPostProcessor {
/**
* Apply this BeanPostProcessor to the given new bean instance before any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* The default implementation returns the given {@code bean} as-is.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/**
* Apply this BeanPostProcessor to the given new bean instance after any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
*
In case of a FactoryBean, this callback will be invoked for both the FactoryBean
* instance and the objects created by the FactoryBean (as of Spring 2.0). The
* post-processor can decide whether to apply to either the FactoryBean or created
* objects or both through corresponding {@code bean instanceof FactoryBean} checks.
*
This callback will also be invoked after a short-circuiting triggered by a
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other BeanPostProcessor callbacks.
*
The default implementation returns the given {@code bean} as-is.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
我们可以获知以下几点:
①在 BeanPostProcessor接口定义了2个方法
postProcessBeforeInitialization(Object bean, String beanName)
postProcessAfterInitialization(Object bean, String beanName)
②什么时候调用postProcessBeforeInitialization(Object bean, String beanName)?
源码注释中是这样说明的:
// Apply this BeanPostProcessor to the given new bean instance before any bean
// initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
// or a custom init-method). The bean will already be populated with property values.
调用构造方法创建bean实例,
调用Setter方法为属性赋值,
然后就可以调用postProcessBeforeInitialization(Object bean, String beanName)。
③什么时候调用postProcessAfterInitialization(Object bean, String beanName)?
源码注释中是这样说明的:
// Apply this BeanPostProcessor to the given new bean instance after any bean
// initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
// or a custom init-method). The bean will already be populated with property values.
调用构造方法创建bean实例,
调用Setter方法为属性赋值,
调用postProcessBeforeInitialization(Object bean, String beanName),
如果bean实现了InitializingBean接口,调用afterPropertiesSet(),
如果bean定义了init-method方法(即在配置文件中设置了init-method属性),调用定义的init-method方法,
调用postProcessAfterInitialization(Object bean, String beanName)。
④方法的参数以及返回值
// @param bean the new bean instance
// @param beanName the name of the bean
// @return the bean instance to use, either the original or a wrapped one;
参数bean:传过来的bean实例(需要被处理)
参数beanName:传过来的bean实例的id
返回值:加工处理后的bean(对传过来的bean做特殊处理,甚至偷梁换柱)
简单看下如何偷梁换柱:
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Car car=new Car();
car.setBrand("奔驰");
return car;//不传bean,把新创建的Car实例传过去
}
(2)代码示例:
Car类:
public class Car implements InitializingBean{
private String brand;
public void setBrand(String brand) {
System.out.println("setBrand()");
this.brand = brand;
}
public Car(){
System.out.println("Constructor()");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean.afterPropertiesSet()");
}
public void my_init(){//自定义的init-method方法
System.out.println("my_init()");
}
}
Bean后置处理器:
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor.postProcessAfterInitialization()");
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor.postProcessBeforeInitialization()");
return bean;
}
}
Bean的配置文件:
<bean class="com.Car" id="car" init-method="my_init">
<property name="brand" value="奥迪">property>
bean>
<bean class="com.MyBeanPostProcessor">bean>
测试类:
public class Main {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
}
}
运行结果:
Constructor()
setBrand()
BeanPostProcessor.postProcessBeforeInitialization()
InitializingBean.afterPropertiesSet()
my_init()
BeanPostProcessor.postProcessAfterInitialization()
(3)我们整理一下:
①通过构造方法创建bean实例:调用构造器;
②为Bean的属性赋值:调用Setter方法;
③将Bean实例传递给Bean后置处理器的postProcessBeforeInitialization();
④如果Bean实现了InitializingBean接口,调用该接口的afterPropertiesSet();
⑤如果bean定义了init-method方法(即在配置文件中设置了init-method属性),调用定义的init-method方法;
⑥将Bean实例传递给Bean后置处理器的postProcessAfterInitialization()。
(4)一些注意点:
①Bean后置处理器:Spring提供的特殊的bean。
②Bean后置处理器需要实现BeanPostProcessor接口。
③需要在Bean的配置文件中,注册bean后置处理器,但不需要设置id属性。IOC容器会自动识别这是个bean后置处理器,自动的使用它。
<bean class="com.MyBeanPostProcessor">bean>
④Bean后置处理器会对容器中所有的bean实例进行处理。可以设置筛选条件,处理特定的某个bean或某些bean(根据bean的beanName或者bean的类型,进行筛选)。
⑤Bean后置处理器的典型应用:检查bean属性的正确性或更改bean的属性。