前言

这两个接口都是spring初始化bean的扩展。允许用户在bean生成的前后进行特殊处理。

BeanFactoryPostProcessor接口是在IOC容器初始化生成BeanDefinition之后可以对BeanDefinition中的数据进行修改。

BeanPostProcessor接口是允许bean在初始化前后做处理。

注:BeanPostProcessor的所有处理在BeanFactoryPostProcessor之后。

场景

比如一般在配置文件中配置的数据库密码都是加密处理的,然后在程序中进行解密,这种操作一般是继承PropertyPlaceholderConfigurer 类,并且重写了processProperties方法

【spring系列】BeanFactoryPostProcessor和BeanPostProcessor接口_ide

可见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进行处理。