前言
有一點(diǎn)Spring基礎(chǔ)的同學(xué)應(yīng)該都知道,Spring的動(dòng)態(tài)代理默認(rèn)使用的是JDK動(dòng)態(tài)代理(對(duì)于非接口的類,用cglib泉手,與JDK動(dòng)態(tài)代理類似,這里不多做解釋)偶器,不清楚JDK動(dòng)態(tài)代理的點(diǎn)這里斩萌。并且,我們知道通過(guò)jdk動(dòng)態(tài)代理屏轰,我們可以拿到一個(gè)代理后的對(duì)象颊郎,而Spring的bean實(shí)例化過(guò)程,就涉及到代理對(duì)象的替換
Spring Bean的生命周期
想知道Spring是如何實(shí)現(xiàn)的動(dòng)態(tài)代理亭枷,必須對(duì)bean的生命周期和實(shí)例化過(guò)程有初步了解袭艺。筆者通過(guò)閱讀源碼,得知一個(gè)bean的實(shí)例化過(guò)程叨粘,是由一系列的BeanPostProcessor(后置處理器)處理的猾编,在bean實(shí)例化之前的注解解析瘤睹,實(shí)例化過(guò)程中確定構(gòu)造器,實(shí)例化后的屬性注入答倡,屬性注入完的初始化步驟轰传,分別由特定的后置處理器來(lái)完成。
如果要在Spring當(dāng)中實(shí)現(xiàn)aop動(dòng)態(tài)代理瘪撇,筆者認(rèn)為主要有兩種思路:
- 1获茬、實(shí)例化之前將BeanDefinition中的class替換為代理類,可以通過(guò)自定義BeanFactoryPostProcessor或者ImportBeanDefinitionRegisterar來(lái)實(shí)現(xiàn)
- 2倔既、實(shí)例化完成之后恕曲,通過(guò)自定義的BeanPostProcessor將對(duì)象替換成代理對(duì)象
由于jdk動(dòng)態(tài)代理和cglib動(dòng)態(tài)代理,都只提供了獲取代理對(duì)象的方法渤涌,因此我們可以猜測(cè)Spring是利用第二種方式實(shí)現(xiàn)的佩谣。
猜想驗(yàn)證
下面是一段aop切面的demo:
@Aspect
@Component
public class MyAspect {
@Autowired
private MyService myService;
@Pointcut("execution(* com.lwl.controller.MyController.testAop(..))")
public void testAop(){}
@Around("testAop()")
public Object aopWeaveing(ProceedingJoinPoint joinPoint) throws Throwable {
//代理代碼,忽略
}
}
下面是被代理的方法和類:
@RestController
@RequestMapping("/aop")
public class MyController {
@GetMapping("test")
@AssertLogin
public String testAop(){
//業(yè)務(wù)代碼实蓬,忽略
}
}
bean的實(shí)例化過(guò)程主要發(fā)生在context的refresh方法中的finishBeanFactoryInitialization方法茸俭,其中
調(diào)用了DefaultLisableBeanFactory的preInstantiateSingletons,通過(guò)getBean(beanName)來(lái)實(shí)例化bean
因此我們跟蹤到執(zhí)行了自定義beanPostProcessor的AbstractAutowireCapableBeanFactory的initializeBean方法當(dāng)中:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//忽略不重要的代碼
//wrappedBean即bean對(duì)象
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//調(diào)用beanPostProcessor的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//調(diào)用bean中實(shí)現(xiàn)的afterPropertiesSet或被@PostConstuct注解修飾的方法安皱,即初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
if (mbd == null || !mbd.isSynthetic()) {
//調(diào)用beanPostProcessor的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
這里需要明確的是调鬓,beanPostProcessor的兩個(gè)方法postProcessBeforeInitialization和postProcessAfterInitialization都能夠替換對(duì)象,區(qū)別在于postProcessBeforeInitialization在bean執(zhí)行初始化方法之前執(zhí)行酌伊,簡(jiǎn)單思考一下腾窝,我們對(duì)對(duì)象進(jìn)行代理時(shí),很可能需要用到該bean對(duì)象初始化之后的屬性腺晾,因此我們猜測(cè)代理的過(guò)程發(fā)生在初始化之后的postProcessAfterInitialization過(guò)程中燕锥。
筆者將斷點(diǎn)打在調(diào)用applyBeanPostProcessorsAfterInitialization方法之前辜贵,可以看到此時(shí)的wrapperBean還是MyController
斷點(diǎn)往下走悯蝉,執(zhí)行完applyBeanPostProcessorsAfterInitialization方法,發(fā)現(xiàn)wrappedBean已經(jīng)變成了CGLib動(dòng)態(tài)代理對(duì)象:
這就驗(yàn)證了我們之前的猜測(cè)
實(shí)現(xiàn)原理分析
我們進(jìn)入applyBeanPostProcessorsAfterInitialization方法看看spring到底做了什么事
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍歷容器中所有的beanPostProcessor托慨,執(zhí)行postProcessAfterInitialization方法
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
可以看到該方法中遍歷了spring容器里所有的beanPostProcessor鼻由,并挨個(gè)執(zhí)行postProcessAfterInitialization。由于筆者是在平時(shí)開(kāi)發(fā)的springboot環(huán)境中隨便寫(xiě)了一個(gè)aop類做調(diào)試厚棵,因此此時(shí)的容器中有非常多的后置處理器蕉世,簡(jiǎn)單看一下一共有三十個(gè):
目前我們能確定的是,一定是某一個(gè)后置處理器執(zhí)行完了postProcessAfterInitialization方法婆硬,才將對(duì)象替換成了代理對(duì)象狠轻,那如何從這么多的beanPostProcessor中找到那個(gè)兇手??jī)煞N方法:
- 1彬犯、還是用之前打斷點(diǎn)的方法向楼,看看哪一個(gè)后置處理器執(zhí)行完以后對(duì)象發(fā)生了改變查吊,但是這里有三十多個(gè)后置處理器,作為一個(gè)有追求的程序員考慮到算法時(shí)間復(fù)雜度為O(n)湖蜕,不行這個(gè)方法需要優(yōu)化
-
2逻卖、靠猜- -筆者死磕源碼的經(jīng)歷,大部分情況靠猜昭抒,事實(shí)上百分之八十都能猜對(duì)评也。這三十個(gè)beanPostProcessor中,從名字上看灭返,似乎只有數(shù)組下標(biāo)為5的AnnotationAwareAspectJAutoProxyCreator看起來(lái)比較可疑(又是Aspect又是AutoProxy的)
因此我們將斷點(diǎn)條件修改為只有beanPostProcessor為該對(duì)象時(shí)才暫停:
image.png
繼續(xù)調(diào)試盗迟,成功進(jìn)入斷點(diǎn),執(zhí)行之前為MyController
image.png
斷點(diǎn)執(zhí)行完以后對(duì)象變成了Cglib代理對(duì)象:
image.png
猜想再次被驗(yàn)證了熙含,那么我們的重點(diǎn)就轉(zhuǎn)換為查看這個(gè)beanPostProcessor中究竟做了什么诈乒,一路跟蹤:
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//重點(diǎn)看這個(gè)方法,它返回了代理后的對(duì)象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//根據(jù)bean的類型和bean的名稱婆芦,獲取與該類相關(guān)的切面
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//此處創(chuàng)建代理對(duì)象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return bean;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
//從切面對(duì)象中提取我們定義的增強(qiáng)邏輯代碼怕磨,構(gòu)造成proxyFactory代理工廠
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//通過(guò)代理工廠創(chuàng)建代理
return proxyFactory.getProxy(getProxyClassLoader());
}
//該方法為proxyFactory中的getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
調(diào)試發(fā)現(xiàn)createAopProxy()返回了一個(gè)CglibAopProxy,說(shuō)明此時(shí)使用的是cglib動(dòng)態(tài)代理
而CglibAopProxy的getProxy里面就是我們非常熟悉的cglib動(dòng)態(tài)代理的代碼了:
public Object getProxy(@Nullable ClassLoader classLoader) {
//rootClass即MyController.class
Class<?> rootClass = this.advised.getTargetClass();
Class<?> proxySuperClass = rootClass;
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
//根據(jù)要代理的類生成callback消约,這個(gè)是重點(diǎn)
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
return createProxyClassAndInstance(enhancer, callbacks);
}
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
//advised即之前創(chuàng)建好的proxyFactory肠鲫,包含了我們交給spring管理的所有Aspect
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
//將切面構(gòu)造成Callback,主要看這個(gè)類
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
... ...
}
//構(gòu)造的callback:
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
//重點(diǎn)看重寫(xiě)的intercept方法
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
//如果代理對(duì)象被設(shè)置為可以暴露或粮,則將當(dāng)前的代理對(duì)象注入
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//把切面的增強(qiáng)邏輯轉(zhuǎn)換成list
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
//如果沒(méi)有增強(qiáng)邏輯导饲,則直接執(zhí)行原來(lái)的方法
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
//有增強(qiáng)邏輯,則根據(jù)spring aop配置規(guī)則確定執(zhí)行順序
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
}
}
總結(jié)
Spring的aop氯材,是在bean被實(shí)例化并初始化之后渣锦,通過(guò)beanPostProcessor的postProcessAfterInitialization,通過(guò)cglib(jdk動(dòng)態(tài)代理)氢哮,在實(shí)際邏輯執(zhí)行前后插入我們的增強(qiáng)邏輯