(一)Spring IoC源码-3.其他特性的实现原理-03BeanPostProcessor的实现

BeanPostProcessor是Bean的后置处理器,它可以监听容器触发的事件。
BeanPostProcessor是一个接口类,它有两个接口方法: postProcessBeforeInitialization(Object bean, String beanName),在Bean的初始化前提供回调入口;另一个是postProcessAfterInitialization(Object bean, String beanName),在Bean的初始化后提供回调入口。

BeanPostProcessor实现原理
public interface BeanPostProcessor {

    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

之前在介绍AbstractAutowireCapableBeanFactory.doCreateBean(String, RootBeanDefinition, Object[])时,你一定注意到这样的几行代码

//完成bean的依赖注入
populateBean(beanName, mbd, instanceWrapper);
//到这里bean的生成和依赖注入已经完成了,这个方法开始对bean进行初始化
//初始化过程包含了对Bean的后置处理器BeanPostProcessor的postProcessBeforeInitialization方法和postProcessAfterInitialization方法的调用
if (exposedObject != null) {
    exposedObject = initializeBean(beanName, exposedObject, mbd);
}

以下是Spring源码中对bean进行初始化的逻辑。从源码中我们可以看到是先通过applyBeanPostProcessorsBeforeInitialization()方法使用注册的BeanPostProcessor的postProcessBeforeInitialization()方法依次回调,然后是通过invokeInitMethods()方法依次调用当前bean对应的初始化方法,再通过applyBeanPostProcessorsAfterInitialization方法使用注册的BeanPostProcessor的postProcessorAfterInitialization()方法依次进行回调。
AbstractAutowireCapableBeanFactory.initializeBean(String, Object, RootBeanDefinition)

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }
    //对Bean的后置处理器BeanPostProcessor的postProcessBeforeInitialization方法的调用
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    //调用bean的初始化方法,初始化方法通过inti-method属性指定。
    //如果bean实现了InitializingBean接口,那么bean的afterPropertiesSet()实现也会被调用
    if (wrappedBean != null) {
        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        //对Bean的后置处理器BeanPostProcessor的postProcessAfterInitialization方法的调用
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
    }

    return wrappedBean;
}
  1. 实例化Bean
  2. 调用BeanPostProcessor的postProcessBeforeInitialization方法
  3. 调用bean实例的初始化方法
  4. 调用BeanPostProcessor的postProcessAfterInitialization方法
BeanPostProcessor示例

BeanPostProcessor的使用非常简单,只需要通过实现接口类BeanPostProcessor设计一个具体的后置处理器,然后将其添加到Bean配置文件中。
首先定义Bean。

public class MyBean {

}

实现后置处理器。

public class MyBeanPostPrcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("对象" + beanName + "开始实例化");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("对象" + beanName + "实例化完成");
        return bean;
    }
}

将定义的Bean和后置处理器添加到Bean配置文件

<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="myBean" class="container.MyBean"></bean>
    <bean class="container.MyBeanPostPrcessor"></bean>
</beans>

测试。

public class MyBeanPostPrcessorTest {
    @Test
    public void test1() {
        XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("MyBean.xml"));
        MyBeanPostPrcessor beanPostProcessor = new MyBeanPostPrcessor();
        bf.addBeanPostProcessor(beanPostProcessor);
        bf.getBean("myBean");
    }

    @Test
    public void test2() {
        AbstractApplicationContext aac = new ClassPathXmlApplicationContext("MyBean.xml");
        aac.getBean("myBean");
    }
}

分别运行test1方法和test2方法。结果分别为

对象myBean开始实例化
对象myBean实例化完成

BeanFactory和ApplicationContext对待bean后置处理器的不同
观察test1和test2方法的实现,你会发现BeanFactory和ApplicationContext对待bean后置处理器稍有不同。ApplicationContext会自动检测在配置文件中实现了BeanPostProcessor接口的所有bean,并把它们注册为后置处理器,然后在容器创建bean的适当时候调用它。而使用BeanFactory实现的时候,bean后置处理器必须显式地去注册.

多个BeanPostProcessor实现的回调顺序
假如我们使用了多个的BeanPostProcessor的实现类,那么如何确定回调顺序呢?

将我们自定义的BeanPostProcessor实现类同时实现Ordered接口,然后Spring将根据Ordered接口定义的getOrder()方法的返回值来决定BeanPostProcessor回调的先后顺序,getOrder()返回值越小的越先进行回调。此外,实现了Ordered接口的BeanPostProcessor总是比没有实现Ordered接口的BeanPostProcessor先进行回调。

public class MyBeanPostPrcessor2 implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("对象" + beanName + "开始实例化");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("对象" + beanName + "实例化完成");
        return bean;
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

本文已收录于Spring源码札记专栏

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值