认识BeanPostProcessor接口

PostProcessor:后处理器;
BeanPostProcessor:Bean的后处理器(处理的对象是bean)

(1)看一下BeanPostProcessor接口的源码:

public interface BeanPostProcessor {
    /**
     * Apply this BeanPostProcessor to the given new bean instance before any bean
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     * 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.
     * 

The default implementation returns the given {@code bean} as-is. * @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; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */ @Nullable default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } /** * Apply this BeanPostProcessor to the given new bean instance after any bean * initialization callbacks (like InitializingBean's {@code afterPropertiesSet} * 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. *

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} checks. *

This callback will also be invoked after a short-circuiting triggered by a * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method, * in contrast to all other BeanPostProcessor callbacks. *

The default implementation returns the given {@code bean} as-is. * @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; * if {@code null}, no subsequent BeanPostProcessors will be invoked * @throws org.springframework.beans.BeansException in case of errors * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */ @Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }

我们可以获知以下几点:
①在 BeanPostProcessor接口定义了2个方法

postProcessBeforeInitialization(Object bean, String beanName)
postProcessAfterInitialization(Object bean, String beanName)

②什么时候调用postProcessBeforeInitialization(Object bean, String beanName)?
源码注释中是这样说明的:

     // Apply this BeanPostProcessor to the given new bean instance before any bean
     // initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     // or a custom init-method). The bean will already be populated with property values.

调用构造方法创建bean实例,
调用Setter方法为属性赋值,
然后就可以调用postProcessBeforeInitialization(Object bean, String beanName)。

③什么时候调用postProcessAfterInitialization(Object bean, String beanName)?
源码注释中是这样说明的:

     // Apply this BeanPostProcessor to the given new bean instance after any bean
     // initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     // or a custom init-method). The bean will already be populated with property values.

调用构造方法创建bean实例,
调用Setter方法为属性赋值,
调用postProcessBeforeInitialization(Object bean, String beanName),
如果bean实现了InitializingBean接口,调用afterPropertiesSet(),
如果bean定义了init-method方法(即在配置文件中设置了init-method属性),调用定义的init-method方法,
调用postProcessAfterInitialization(Object bean, String beanName)。

④方法的参数以及返回值

     // @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;

参数bean:传过来的bean实例(需要被处理)
参数beanName:传过来的bean实例的id
返回值:加工处理后的bean(对传过来的bean做特殊处理,甚至偷梁换柱)

简单看下如何偷梁换柱:

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        Car car=new Car();
        car.setBrand("奔驰");
        return car;//不传bean,把新创建的Car实例传过去
    }

(2)代码示例:
Car类:

public class Car implements InitializingBean{
    private String brand;

    public void setBrand(String brand) {
        System.out.println("setBrand()");
        this.brand = brand;
    }

    public Car(){
        System.out.println("Constructor()");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean.afterPropertiesSet()");
    }

    public void my_init(){//自定义的init-method方法
        System.out.println("my_init()");
    }
}

Bean后置处理器:

public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor.postProcessAfterInitialization()");
        return bean;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor.postProcessBeforeInitialization()");
        return bean;
    }
}

Bean的配置文件:

    <bean class="com.Car" id="car" init-method="my_init">
        <property name="brand" value="奥迪">property>
    bean>

    
    <bean class="com.MyBeanPostProcessor">bean>

测试类:

public class Main {
    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    }
}

运行结果:
Constructor()
setBrand()
BeanPostProcessor.postProcessBeforeInitialization()
InitializingBean.afterPropertiesSet()
my_init()
BeanPostProcessor.postProcessAfterInitialization()

(3)我们整理一下:
①通过构造方法创建bean实例:调用构造器;
②为Bean的属性赋值:调用Setter方法;
③将Bean实例传递给Bean后置处理器的postProcessBeforeInitialization();
④如果Bean实现了InitializingBean接口,调用该接口的afterPropertiesSet();
⑤如果bean定义了init-method方法(即在配置文件中设置了init-method属性),调用定义的init-method方法;
⑥将Bean实例传递给Bean后置处理器的postProcessAfterInitialization()。

(4)一些注意点:
①Bean后置处理器:Spring提供的特殊的bean。
②Bean后置处理器需要实现BeanPostProcessor接口。
③需要在Bean的配置文件中,注册bean后置处理器,但不需要设置id属性。IOC容器会自动识别这是个bean后置处理器,自动的使用它。

<bean class="com.MyBeanPostProcessor">bean>

④Bean后置处理器会对容器中所有的bean实例进行处理。可以设置筛选条件,处理特定的某个bean或某些bean(根据bean的beanName或者bean的类型,进行筛选)。
⑤Bean后置处理器的典型应用:检查bean属性的正确性或更改bean的属性。

你可能感兴趣的:(Spring,spring)