前言
這兩個接口都是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進行處理。