Bean的后处理
- BeanPostProcessor的用法
bean级别的处理,针对某个具体的bean进行处理,接口提供了两个方法,分别是bean初始化前和bean初始化后执行方法。
postProcessBeforeInitialization:该方法主要针对spring在bean初始化时调用初始化方法前进行自定义处理。
postProcessAfterInitialization:该方法主要针对spring在bean初始化时调用初始化方法后进行自定义处理。 - 自定义BeanPostProcessor
bean:
@Data
public class Cat {
private String name;
private int age;
public void say() {
System.out.println("name:" + name);
System.out.println("age:" + age);
}
}
自定义BeanPostProcessor:
/**
* 自定义BeanPostProcessor后处理器
*/
public class CatBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Cat) {
System.out.println("bean Cat初始化之前...");
//输出原始属性
Cat cat = (Cat) bean;
cat.say();
return bean;
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Cat) {
System.out.println("bean Cat初始化之后...");
//修改属性值,并返回
Cat cat = (Cat) bean;
cat.setName("hello maomi");
cat.setAge(3);
return cat;
}
return bean;
}
}
配置文件:
<!--自定义BeanPostProcessor的测试-->
<!--配置bean并初始化-->
<bean id="cat" class="com.example.test.demo.spring.BeanPostProcessor.Cat" >
<property name="name" value="HelloKitty" />
<property name="age" value="1" />
</bean>
<bean id="catBeanPostProcessor" class="com.example.test.demo.spring.BeanPostProcessor.CatBeanPostProcessor" />
测试:
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:conf/application.xml");
Cat bean = context.getBean(Cat.class);
bean.say();
bean Cat初始化之前...
name:HelloKitty
age:1
bean Cat初始化之后...
name:hello maomi
age:3
BeanPostProcessor原理:
populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值的
initializeBean(beanName, exposedObject, mbd){
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
invokeInitMethods(beanName, wrappedBean, mbd);//执行自定义初始化方法
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
applyBeanPostProcessorsBeforeInitialization:
遍历容器中所有的BeanPostProcessor
:挨个执行PostProcessorsBeforeInitialization
,一旦返回null,就跳出for循环,不会执行后面的BeanPostProcessor.PostProcessorsBeforeInitialization
Spring底层对BeanPostProcessor
的使用:
bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async等都是使用BeanPostProcessor
实现的。
例如:组件里注入ioc容器。
组件实现ApplicationContextAware
即可。
ApplicationContextAwareProcessor
(BeanPostProcessor的一个实现类)的postProcessBeforeInitialization
方法判断当前bean是不是实现了ApplicationContextAware
,是的话,调用bean的set方法,((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
@Component
public class Dog implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
public Dog() {
System.out.println("dog...constructor...");
}
//对象创建并赋值之后调用初始化
@PostConstruct
public void init() {
System.out.println("Dog...@PostConstruct...");
}
//容器移除对象之前调用销毁
@PreDestroy
public void destroy() {
System.out.println("Dog ...@PreDestroy...");
}
}
其他BeanPostProcessor
实现类:
BeanValidationPostProcessor
:数据校验的,当对象创建完,给JavaBean赋值还可以做数据校验;
InitDestroyAnnotationBeanPostProcessor
:处理@PostConstruct
以及@PreDestroy
注解的。(使用反射执行的注解标注的方法)
AutowiredAnnotationBeanPostProcessor
:处理@Autowired
注解,在对象创建完后,处理被@Autowired
注解标注的属性
BeanPostProcessor与BeanFactoryPostProcessor的区别
BeanPostProcessor:bean级别的处理,针对某个具体的bean进行处理。
执行时机:
实例化bean之后执行,接口提供了两个方法,分别是bean初始化前和bean初始化后执行方法。
BeanFactoryPostProcessor:BeanFactory级别的处理,是针对整个Bean的工厂 进行处理。
执行时机:
接口提供postProcessBeanFactory方法,可以在当前BeanFactory初始化后,beanDefinition已经loaded,但是bean还未创建前 进行调用,也就是,bean实例化之前执行,可以修改bean的定义属性。