前言
这两个接口都是spring初始化bean的扩展。允许用户在bean生成的前后进行特殊处理。
BeanFactoryPostProcessor接口是在IOC容器初始化生成BeanDefinition
之后可以对BeanDefinition
中的数据进行修改。
BeanPostProcessor接口是允许bean在初始化前后做处理。
注:BeanPostProcessor的所有处理在BeanFactoryPostProcessor之后。
场景
比如一般在配置文件中配置的数据库密码都是加密处理的,然后在程序中进行解密,这种操作一般是继承PropertyPlaceholderConfigurer
类,并且重写了processProperties
方法
可见PropertyPlaceholderConfigurer是实现了BeanFactoryPostProcessor接口做到在bean初始化之前修改了属性值。
另外xml中配置的属性值经常会有${jdbc.driver}
,这种配置也可以通过此接口进行属性的替换。
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 配置连接池属性 -->
<property name="driverClass" value="${jdbc.driver}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
代码示例
1.BeanFactoryPostProcessor示例
spring.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userInfo" class="com.example.model.UserInfo" init-method="init" >
<property name="name" value="aa"></property>
</bean>
<!-- 实现了BeanFactoryPostProcessor接口-->
<bean id="testBeanFactoryPostProcessor" class="com.example.model.TestBeanFactoryPostProcessor"/>
</beans>
TestBeanFactoryPostProcessor.java
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("***********BeanFactoryPostProcessor***********");
}
}
Test.java
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml");
UserInfo userinfo = (UserInfo)context.getBean("userInfo");
System.out.println(userinfo.getName());
}
输出:
BeanFactoryPostProcessor
21:42:53.923 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘userInfo’
这里是 UserInfo init
aa
2.BeanPostProcessor示例
spring.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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userInfo" class="com.example.model.UserInfo">
<property name="name" value="aa"></property>
</bean>
<!--此实现BeanPostProcessor接口-->
<bean id="testBeanPostProcessor" class="com.example.model.TestBeanPostProcessor"/>
</beans>
UserInfo.java
InitializingBean.afterPropertiesSet会在bean实例化之后执行。类似于在配置文件中配置init-method
public class UserInfo implements InitializingBean {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("这里是 UserInfo init");
}
}
TestBeanPostProcessor.java
public class TestBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(" BeanPostProcessor,在bean生成之前处理 beanName:"+beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(" BeanPostProcessor,在bean生成之后处理 beanName:"+beanName);
return bean;
}
}
Test.java
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml");
UserInfo userinfo = (UserInfo)context.getBean("userInfo");
System.out.println(userinfo.getName());
}
输出:
21:13:02.042 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@532760d8
21:13:02.449 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 2 bean definitions from class path resource [spring.xml]
21:13:02.508 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘testBeanPostProcessor’
21:13:02.567 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘userInfo’
BeanPostProcessor,在bean生成之前处理 beanName:userInfo
这里是 UserInfo init
BeanPostProcessor,在bean生成之后处理 beanName:userInfo
aa
3.两个接口对比
配置文件中同样加载bean
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userInfo" class="com.example.model.UserInfo" init-method="init" >
<property name="name" value="aa"></property>
</bean>
<bean id="testBeanPostProcessor" class="com.example.model.TestBeanPostProcessor"/>
<bean id="testBeanFactoryPostProcessor" class="com.example.model.TestBeanFactoryPostProcessor"/>
</beans>
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("***********BeanFactoryPostProcessor***********");
}
}
public class TestBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(" BeanPostProcessor,在bean生成之前处理 beanName:"+beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(" BeanPostProcessor,在bean生成之后处理 beanName:"+beanName);
return bean;
}
}
执行Test.java之后
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml");
UserInfo userinfo = (UserInfo)context.getBean("userInfo");
System.out.println(userinfo.getName());
}
输出:
BeanFactoryPostProcessor
21:45:22.435 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘testBeanPostProcessor’
21:45:22.439 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘userInfo’
BeanPostProcessor,在bean生成之前处理 beanName:userInfo
这里是 UserInfo init
BeanPostProcessor,在bean生成之后处理 beanName:userInfo
aa
ork.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean ‘userInfo’
BeanPostProcessor,在bean生成之前处理 beanName:userInfo
这里是 UserInfo init
BeanPostProcessor,在bean生成之后处理 beanName:userInfo
aa
BeanFactoryPostProcessor的处理在BeanPostProcessor之前。另外BeanFactoryPostProcessor可以对BeanDefinition等进行处理,但是BeanPostProcessor就有局限性,只能对bean进行处理。