# BeanFactoryPostProcessor和BeanPostProcessor

BeanFactoryPostProcessor和BeanPostProcessor，这两个接口，都是Spring初始化bean时对外暴露的扩展点。两个接口名称看起来很相似，但作用及使用场景却不同，分析如下：

## 1、BeanFactoryPostProcessor接口

该接口的定义如下：

public interface BeanFactoryPostProcessor {

```java
/**
 * Modify the application context's internal bean factory after its standard
 * initialization. All bean definitions will have been loaded, but no beans
 * will have been instantiated yet. This allows for overriding or adding
 * properties even to eager-initializing beans.
 * @param beanFactory the bean factory used by the application context
 * @throws org.springframework.beans.BeansException in case of errors
 */
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
```

} 实现该接口，可以在spring的bean创建之前，修改bean的定义属性。也就是说，Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据，并可以根据需要进行修改，例如可以把bean的scope从singleton改为prototype，也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor，并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。

> 注意：BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后，在bean实例化之前执行的。接口方法的入参是ConfigurrableListableBeanFactory，使用该参数，可以获取到相关bean的定义信息。

## 2、BeanPostProcessor接口

该接口的定义如下：

public interface BeanPostProcessor {

```java
/**
 * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
 * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code>
 * or a custom init-method). The bean will already be populated with property values.
 * The returned bean instance may be a wrapper around the original.
 * @param bean the new bean instance
 * @param beanName the name of the bean
 * @return the bean instance to use, either the original or a wrapped one
 * @throws org.springframework.beans.BeansException in case of errors
 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
 */
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

/**
 * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
 * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code>
 * or a custom init-method). The bean will already be populated with property values.
 * The returned bean instance may be a wrapper around the original.
 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
 * post-processor can decide whether to apply to either the FactoryBean or created
 * objects or both through corresponding <code>bean instanceof FactoryBean</code> checks.
 * <p>This callback will also be invoked after a short-circuiting triggered by a
 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
 * in contrast to all other BeanPostProcessor callbacks.
 * @param bean the new bean instance
 * @param beanName the name of the bean
 * @return the bean instance to use, either the original or a wrapped one
 * @throws org.springframework.beans.BeansException in case of errors
 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
 * @see org.springframework.beans.factory.FactoryBean
 */
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
```

} BeanPostProcessor，可以在spring容器实例化bean之后，在执行bean的`初始化方法`前后，添加一些自己的处理逻辑。这里说的`初始化方法`，指的是下面两种：

1）bean实现了InitializingBean接口，对应的方法为afterPropertiesSet

2）在bean定义的时候，通过init-method设置的方法

> 注意：BeanPostProcessor是在spring容器加载了bean的定义文件并且实例化bean之后执行的。BeanPostProcessor的执行顺序是在BeanFactoryPostProcessor之后。

## 3、实战

BeanFactoryPostProcessor

```java
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("1. 调用BeanFactoryPostProcessor的postProcessBeanFactory");
        BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");
        MutablePropertyValues pv = bd.getPropertyValues();
        pv.addPropertyValue("remark", "BeanFactoryPostProcessor中修改之后的remark");
    }
}
```

BeanPostProcessor

```java
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("myJavaBean".equals(beanName)){
            System.out.println("3. 调用BeanPostProcessor.postProcessBeforeInitialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("myJavaBean".equals(beanName)){
            System.out.println("7. 调用BeanPostProcessor.postProcessAfterInitialization");
        }
        return bean;
    }
}
```

配置类

```java
@Configuration
public class MyConfig {
    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public MyJavaBean myJavaBean() {
        MyJavaBean bean = new MyJavaBean();
        bean.setRemark("原始remark");
        return bean;
    }

    @Bean
    public MyBeanFactoryPostProcessor myBeanFactoryPostProcessor(){
        return new MyBeanFactoryPostProcessor();
    }

    @Bean
    public MyBeanPostProcessor myBeanPostProcessor(){
        return new MyBeanPostProcessor();
    }
}
```

Bean

```java
public class MyJavaBean implements InitializingBean, DisposableBean {
    private String desc;
    private String remark;

    public MyJavaBean() {
        System.out.println("2 Bean的无参构造函数");
    }

    public MyJavaBean(String desc, String remark) {
        this.desc = desc;
        this.remark = remark;
        System.out.println("2 Bean的全参构造函数");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("4. 调用PostConstruct方法");
    }


    public String getDesc() {
        return desc;
    }


    public void setDesc(String desc) {
        System.out.println("调用setDesc方法");
        this.desc = desc;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        System.out.println("调用setRemark方法");
        this.remark = remark;
        System.out.println("remark = " + this.remark);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5. 调用InitializingBean.afterPropertiesSet方法");
        this.desc = "afterPropertiesSet中修改之后的desc";
    }

    public void initMethod() {
        System.out.println("6. 调用Bean的init方法");
    }


    @Override
    public void destroy() throws Exception {
        System.out.println("8. 调用DisposableBean.destroy");
    }

    public void destroyMethod() {
        System.out.println("9. 调用Bean的destroy方法");
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("[desc：").append(desc);
        builder.append("， remark：").append(remark).append("]");
        return builder.toString();
    }
}
```

启动类

```java
@SpringBootApplication
public class PostProcessorApplication {


    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(PostProcessorApplication.class, args);
        MyJavaBean bean = (MyJavaBean) applicationContext.getBean("myJavaBean");
        System.out.println("=======================结果====================");
        System.out.println("desc：" + bean.getDesc());
        System.out.println("remark：" + bean.getRemark());
        System.out.println("======================结果====================");

    }

}
```

执行顺序：

```java
1. 调用BeanFactoryPostProcessor的postProcessBeanFactory
2 Bean的无参构造函数
调用setRemark方法
remark = 原始remark
调用setRemark方法
remark = BeanFactoryPostProcessor中修改之后的remark
******beanName = myJavaBean
******beanFactory = org.springframework.beans.factory.support.DefaultListableBeanFactory
******applicationContext = org.springframework.context.annotation.AnnotationConfigApplicationContext
3. 调用BeanPostProcessor.postProcessBeforeInitialization
4. 调用PostConstruct方法
5. 调用InitializingBean.afterPropertiesSet方法
6. 调用Bean的init方法
7. 调用BeanPostProcessor.postProcessAfterInitialization
=======================结果====================
desc：afterPropertiesSet中修改之后的desc
remark：BeanFactoryPostProcessor中修改之后的remark
======================结果====================
8. 调用DisposableBean.destroy
9. 调用Bean的destroy方法
```

> BeanFactoryPostProcessor对Bean属性的修改延迟到了Bean初始化完成之后才执行

## 4、进一步深入分析

在使用ApplicationContext启动spring容器的时候，在AbstractApplicationContext.refresh()方法中，完成相关初始化工作：

![img](https://picgo.6and.ltd/img/20140628121008984)

1）BeanFactoryPostProcessor.postProcessBeanFactory，是在第5步执行的

2）而BeanPostProcessor的执行，取决于配置文件中bean的定义，如果定义的bean是singleton并且不是抽象类，也不延迟初始化，则BeanPostProcessor是在第11步中执行；而对于prototype的bean，BeanPostProcessor是在程序getBean的时候执行的。在第6步中，调用registerBeanPostProcessors方法，注册所有实现BeanPostProcessor接口的bean

## 5、总结

1、创建（调用构造函数） 2、set属性（set方法注入属性） 3、判断是否实现BeanNameAware接口，并调用接口的setBeanName方法 4、判断是否实现BeanFactoryAware接口，并调用接口的setBeanFactory方法 5、判断是否实现ApplicationContextAware接口，并调用接口的setApplicationContext方法 6、判断是否实现BeanPostProcessor接口，并调用接口的postProcessBeforeInitialization方法 7、判断是否实现InitializingBean接口，并调用接口的afterPropertiesSet方法 8、判断是否自定义init方法，并调用 9、判断是否实现BeanPostProcessor接口（同6），并调用接口的postProcessAfterInitialization方法 10、业务代码中Bean对象的使用 11、当容器销毁时，判断是否实现DisposableBean接口，并调用接口的destroy方法 12、判断是否自定义销毁方法，并调用

对于 `BeanNameAware BeanFactoryAware ApplicationContextAware` 这3个接口我们平时很少实现它，一般用于让Bean能够感知到`BeanName BeanFactory ApplicationContext`

```java
public class MyJavaBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware {

    private String beanName;
    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;


    @Override
    public void setBeanName(String s) {
        this.beanName = s;
        System.out.println("******beanName = " + this.beanName);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
        System.out.println("******beanFactory = " + this.beanFactory);

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("******applicationContext = " + this.applicationContext);
    }
}
```

## 参考

[Spring的BeanFactoryPostProcessor和BeanPostProcessor](https://blog.csdn.net/caihaijiang/article/details/35552859)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://huolala.gitbook.io/code/spring/spring/beanfactorypostprocessor-he-beanpostprocessor.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
