摘要
Spring IoC容器允许BeanFactoryPostProcessor在容器实例化任何bean之前读取bean的定义(配置元数据),并可以修改它。
BeanFactoryPostProcessor:
BeanFactory的后置处理器(处理的对象是BeanFactory),BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的
BeanPostProcessor:
Bean的后置处理器(处理的对象是Bean);可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。
使用
定义一个bean
package top.yuyufeng.learn.spring.bean;
/**
* @author yuyufeng
* @date 2018/10/10.
*/
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//getters and setters
}
定义 BeanFactoryPostProcessor
package top.yuyufeng.learn.spring.postprocessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import top.yuyufeng.learn.spring.bean.Person;
/**
* @author yuyufeng
* @date 2018/10/10.
*/
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
if (bd.getBeanClassName().equals(Person.class.getName())) {
System.out.println("#ProcessBeanFactory " + beanName);
MutablePropertyValues mp = bd.getPropertyValues();
mp.add("age", 0);
}
}
}
}
定义BeanPostProcessor
package top.yuyufeng.learn.spring.postprocessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import top.yuyufeng.learn.spring.bean.Person;
/**
* @author yuyufeng
* @date 2018/10/10.
*/
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean.getClass().equals(Person.class)) {
Person person = (Person) bean;
person.setName(person.getName() + "bf");
System.out.println("#MyBeanPostProcessor.Before " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean.getClass().equals(Person.class)) {
Person person = (Person) bean;
person.setName(person.getName() + "af");
System.out.println("#MyBeanPostProcessor. After " + beanName);
}
return bean;
}
}
配置Spring启动xml : spring-process.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="propertyPlaceholderConfigurerDao"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="order" value="1"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="locations">
<list>
<value>classpath:config.properties</value>
</list>
</property>
</bean>
<context:component-scan base-package="top.yuyufeng.learn.spring.postprocessor"/>
<bean id="person1" class="top.yuyufeng.learn.spring.bean.Person">
<constructor-arg index="0" value="小鱼"/>
<constructor-arg index="1" value="25"/>
</bean>
<bean id="person2" class="top.yuyufeng.learn.spring.bean.Person">
<constructor-arg index="0" value="小小"/>
<constructor-arg index="1" value="26"/>
</bean>
</beans>
调试:
package top.yuyufeng.learn.spring.postprocessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import top.yuyufeng.learn.spring.bean.Person;
/**
* @author yuyufeng
* @date 2018/10/10.
*/
public class App {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring/spring-process.xml");
Person p1 = (Person) ac.getBean("person1");
System.out.println(p1);
Person p2 = (Person) ac.getBean("person2");
System.out.println(p2);
}
}
运行结果:
#ProcessBeanFactory person1
#ProcessBeanFactory person2
#MyBeanPostProcessor.Before person1
#MyBeanPostProcessor. After person1
#MyBeanPostProcessor.Before person2
#MyBeanPostProcessor. After person2
Person{name=‘小鱼bfaf’, age=0}
Person{name=‘小小bfaf’, age=0}
我们在BeanFactoryPostProcessor,隐藏了Person对象的年龄,再去初始化对象的。在初始化的前后也可以做一些操作。
Spring的生命周期
看我们调试的打印顺序,我们来看下Spring的生命周期(去配置 init-method和实现InitializingBean接口)
顺序为:
- ProcessBeanFactory
- BeanPostProcessor.Before
- afterPropertiesSet
- initMethod
- BeanPostProcessor. After