在上篇博客中寫道了bean后置處理器InstantiationAwareBeanPostProcessor,只介紹了其中一個方法的作用及用法,現在來看postProcessBeforeInstantiation方法。
一、概述
postProcessBeforeInstantiation方法定義在InstantiationAwareBeanPostProcessor接口中,方法的定義如下,
@Nullable default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return null; }
從上面的代碼中可以看到該方法默認返回null。
二、詳述
postProcessBeforeInstantiation方法是用來做什么的,在看源碼的過程中,在createBean方法中找到了該方法的調用,下面只貼出相關代碼,
try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. //1、調用beanPostProcessor即bean的后置處理器,這里會調用2次后置處理器 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); }
在resolveBeforeInstantiation方法中進行了調用,resolveBeforeInstantiation方法返回值如果不為null,則該方法直接返回bean,也就是說resolveBeforeInstantiation方法至關重要,下面是resolveBeforeInstantiation方法,
@Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { //如果是InstantiationAwareBeanPostProcessor的實例,則執行其postProcessBeforeInstantiation方法 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); //如果上面的postProcessBeforeInstantiation方法返回值不為null,則執行所有beanPostProcessor的postProcessAfterInitialization方法 //bean不為null,則說明postProcesBeforeInstantiation方法中的返回值是一個不為null的對象 if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
在resolveBeforeInstantiation方法中首先調用了applyBeanPostProcessorsBeforeInstantiation方法,該方法中便會調用InstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiation方法,且如果applyBeanPostPorcessorsBeforeInstantiation方法返回值不為null,才會調用applyBeanPostProcessAfterIntialization方法,下面先看applyBeanPostProcessorsBeforeInstantiation方法
@Nullable 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; }
從上面方法的定義看到,該方法會遍歷benaFactory中的beanPostProcessor,並且判斷是否為InstantiationAwareBeanPostPrecessor的類型,如果是執行其postProcessBeforeInstantiation方法,這里默認注冊的beanPostProcessor該方法的返回值均為null。稍后自定義一個BeanPostProcessor實現InstantiationAwareBeanPostProcessor接口。
下面看applyBeanPostProcessAfterIntializtion方法,
@Override public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException { Object result = existingBean; for (BeanPostProcessor processor : getBeanPostProcessors()) { Object current = processor.postProcessAfterInitialization(result, beanName); if (current == null) { return result; } result = current; } return result; }
改方法的邏輯是遍歷beanFactory中的所有的beanPostProcessor,執行其postProcessAfterInitialization方法,該方法定義在BeanPostProcessor接口中,默認返回bean,如下,
@Nullable default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; }
從上面可以看出默認返回的是bean參數的值,也就是如果該方法未實現則默認返回參數中的bean。
再次回到resolveBeforeInstantiation方法,再看其邏輯有以下幾種方法返回值的組合,
1、applyBeanPostProcessBeforeInstantiation返回值為null,則resolveBeforeInstantiation方法返回null;
2、applyBeanPostProcessBeforeInstantiation返回值bean不為null,applyBeanPostProcessAfterInitialization方法返回值為null,則resolveBeforeInstantiationf方法返回值為bean;
3、applyBeanPostProcessBeforeInstantiation返回值bean不為null,applyBeanPostProcessAfterInitialization方法返回值bean1不為為null,則resolveBeforeInstantiationf方法返回值為bean1;
從resolveBeforeInstantiation方法分析,該方法的返回值,直接決定了createBean方法的返回值,也就是說applyBeanPostProcessBeforeInstantiation方法返回的bean不為null,下面的方法不會執行。
再來看調用resolveBeforeInstantiation方法時的注釋
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
大體意思時給BeanPostProcessor一個機會返回代理對象而不是目標對象的實例,所以這里resolveBeforeInstantiation方法返回的必然時一個代理對象(JDK和CGLib)。看下面的例子
自定義的BeanPostProcessor實現了InstantiationAwareBeanPostProcessor
package cn.com.my.test; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor; import org.springframework.stereotype.Component; import net.sf.cglib.proxy.Enhancer; @Component public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub if("userService".equals(beanName)) { UserService us=(UserService)bean; Enhancer enhancer = new Enhancer(); //設置目標類的字節碼文件 enhancer.setSuperclass(UserService.class); //設置回調函數 enhancer.setCallback(new MyMethodInterceptor()); //這里的creat方法就是正式創建代理類 UserService proxyUs = (UserService)enhancer.create(); return proxyUs; } return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName); } }
當beanName等於userUservice時返回的是經過cglib代理后的對象。在MyInstantiationAwareBeanPostProcessor類中僅實現了postProcessBeforeInitialization方法,未實現postProcessAfterInitialization方法,所以resolveBeforeInstantiation方法的返回值即未postProcessBeforeInitialization方法的返回值,在上面的類中就是使用cglib代理后的UserService實例。
代理類MyMethodInterceptor,實現cglib的MethodInterceptor接口
package cn.com.my.test; import java.lang.reflect.Method; import org.springframework.cglib.proxy.MethodProxy; import net.sf.cglib.proxy.MethodInterceptor; public class MyMethodInterceptor implements MethodInterceptor{ @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, net.sf.cglib.proxy.MethodProxy arg3) throws Throwable { // TODO Auto-generated method stub Object object = arg3.invokeSuper(arg0, arg2); return object; } }
下面是測試類
package cn.com.my.test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(Config.class); UserService us=ac.getBean(UserService.class); System.out.println("us:"+us); } }
看下面的結果,
us:cn.com.my.test.UserService$$EnhancerByCGLIB$$ffa582b4@5fe94a96
返回的是UserService的一個經過cglib代理后的對象。到這里發現真好強大,返回的一個代理對象。
三、適用場合
實現InstantiationAwareBeanPostProcessor接口的postProcessBeforeInitialization方法,通過返回一個代理對象的方式,達到改變目標類類型的目的。在不想改變現有類的邏輯而又想借助現有類實現其他功能,就可以使用這種方式。像AOP就是這種實現,AnnotationAwareAspectJAutoProxyCreator類便是InstantiationAwareBeanPostProcessor的一個實現。
原創不易,有不當之處,歡迎指正,謝謝!