认识BeanPostProcessor接口

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

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

public interface BeanPostProcessor {
    /**
     * Apply this BeanPostProcessor to the given new bean instance <i>before</i> 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.
     * <p>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 <i>after</i> 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.
     * <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} 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.
     * <p>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 <i>before</i> 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 <i>after</i> 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的后置处理器 -->
    <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的属性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值