序言
之前文章有介绍采用FactoryBean的方式创建对象,以及使用反射创建对象。
这篇文章继续介绍Spring中创建Bean的形式之一——自定义BeanPostProcessor。
之前在介绍BeanPostProcessor的文章中有提到,BeanPostProcessor接口
的实现中有一个InstantiationAwareBeanPostProcessor接口
而在Spirng源码中的doGetBean方法
中就有针对该接口的判断逻辑,如果有类实现了InstantiationAwareBeanPostProcessor
则可以在对应的方法中进行Bean对象的创建。
源码
去除无用代码,我们这里主要看resolveBeforeInstantiation
方法。如果通过resolveBeforeInstantiation
创建了Bean示例,则return该Bean 不在继续往下走其他流程。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {RootBeanDefinition mbdToUse = mbd;//锁定class,根据设置的class属性或者根据className来解析classClass<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.// 给BeanPostProcessors一个机会来返回代理来替代真正的实例,Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}}
resolveBeforeInstantiation
如果满足if条件,则会走applyBeanPostProcessorsBeforeInstantiation
方法进行对象的创建。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;//如果beforeInstantiationResolved值为null或者true,那么表示尚未被处理,进行后续的处理if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.// 确保Bean确实在此处进行处理// 判断当前mbd是否是合成的,只有在实现aop的时候synthetic的值才为true,并且是否实现了InstantiationAwareBeanPostProcessor接口if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {//确定目标类型Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;}
applyBeanPostProcessorsBeforeInstantiation
获取所有实现了BeanPostProcessors
的类,并强转成InstantiationAwareBeanPostProcessor
类型,调用postProcessBeforeInstantiation
方法进行Bean的创建。
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);if (result != null) {return result;}}}return null;}
测试类
我们针对上面的源码流程,扩展自定义的BeanPostProcessor
进行类的创建。我们这里依然采用上篇文章提到的Cglib动态代理的方式创建我们的对象。
BeforeInstantiation
BeforeInstantiation
是我们想要最终创建的实例对象。
public class BeforeInstantiation {public void doSomeThing(){System.out.println("执行do some thing....");}
}
MyMethodInterceptor
拦截器类,对目标方法进行中间拦截,上篇文章在讲lookup-method
标签时,里面采用Cglib动态代理生成对象的固定写法,创建Enhancer
对象并设置CallBack。
因为我们这里也采用Cglib的方式进行对象的创建,所以也需要设置CallBack。
public class MyMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("目标方法执行之前:" + method);Object o1 = methodProxy.invokeSuper(o, objects);System.out.println("目标方法执行之后:" + method);return o1;}
}
MyInstantiationAwareBeanPostProcessor
自定义InstantiationAwareBeanPostProcessor
接口的扩展类,调用postProcessBeforeInstantiation
方法,采用Cglib的固定写法实现对BeforeInstantiation
对象的创建。
其余方法因为用不到,所以直接return对应类型,没有具体业务逻辑。
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if (beanClass == BeforeInstantiation.class) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(beanClass);enhancer.setCallback(new MyMethodInterceptor());BeforeInstantiation beforeInstantiation = (BeforeInstantiation) enhancer.create();return beforeInstantiation;}return null;}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {return pvs;}@Overridepublic PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}
resolveBeforeInstantiation.xml
xml中声明MyInstantiationAwareBeanPostProcessor
对象和BeforeInstantiation
对象。
<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.xsd"><bean id="myInstantiationAwareBeanPostProcessor" class="org.springframework.resolveBeforeInstantiation.MyInstantiationAwareBeanPostProcessor" /><bean id="beforeInstantiation" class="org.springframework.resolveBeforeInstantiation.BeforeInstantiation"/>
</beans>
main
执行refresh()主流程调用registerBeanPostProcessors
方法创建MyInstantiationAwareBeanPostProcessor
后,会调用addBeanPostProcessor
方法将hasInstantiationAwareBeanPostProcessors()
变量设置为true,当beforeInstantiation
创建时,if 判断 整体为 true,调用我们自定义的扩展类创建beforeInstantiation
对象。
public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("resolveBeforeInstantiation.xml");BeforeInstantiation beanInstantiation = (BeforeInstantiation)ac.getBean("beforeInstantiation");beanInstantiation.doSomething();}