1.@EnableAspectJAutoProxy(proxyTargetClass = true)
就是弄了個"org.springframework.aop.config.internalAutoProxyCreator"::AnnotationAwareAspectJAutoProxyCreator.class的Bean到容器中
2.分析AnnotationAwareAspectJAutoProxyCreator.class類結構
得出了哪些是重要的幾個。
3.查看AnnotationAwareAspectJAutoProxyCreator源碼
=》查看父類AbstractAutoProxyCreator,有setBeanFactory等等各種繼承來的方法
4.又是一頓整理得出了一個圖(???)如下
pic1->AOP功能代碼分析圖
5.分析AbstractAutoProxyCreator。
setBeanFactory有個O標志被重寫了,打開,有個initBeanFactory方法,打開,創(chuàng)建了個advisorRetrievalHelper切面工具,又是O重寫 創(chuàng)建了aspectJAdvisorsBuilder
6.pic1圖里明顯看出有兩個關鍵性方法:
postProcessBeforeInstantiation和postProcessAfterInitialization
顯然是前后處理邏輯了??隙ㄏ瓤辞斑壿媝ostProcessBeforeInstantiation啊
7.postProcessBeforeInstantiation
斷點走起,居然是從這里進去的
所以這個之前分析IOC的createBean里的resolveBeforeInstantiation是AOP實現(xiàn)的關鍵。
8.分析postProcessBeforeInstantiation細節(jié)
8.1 isInfrastructureClass判斷是否基礎Bean
就是那種AOP本身的比如Advice、Pointcut、AopInfrastructureBean等,基礎的這種直接返回不需要代理
8.2 shouldSkip是否要跳過(包含找出切面)
8.2.1找出增強器(那種切面里的@After、@Before的方法)
跟隨斷點跳躍到之前setBeanFactory創(chuàng)建的advisorRetrievalHelper里去了幫忙實現(xiàn)的找增強器
實際上這里面又分兩部分了,一個是找事務的(findCandidateAdvisors)(本次斷點容器和緩存中都就沒用了直接返回空,不是事務,具體可以看aop源碼instan...圖)
另一部分是this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
跳進去看了下,它把所有的beanname拿出來找,去找切面類 找到了我寫的MyLogAspect
(打了切面切面注解)
然后找到了切面類,調用相關封裝的getAdvisors方法去拿增強器了。
其實就是獲取切面類的所有方法(getAdvisorMethods)把每個包含增強那些注解的方法包裝成Advice 放進緩存。
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
而
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
然后
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
switch判斷注解類型 創(chuàng)建不同類型Advice 放進緩存
最終由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()找到了我寫的所有切面的增強方法
最終把整個切面類放到了advisorsCache的ConcurrentHashMap,以切面類的beanname作為key,增強器方法advice集合作為value
9.postProcessAfterInitialization
條件斷點,當beanname = "calculate"時停住。找出增強器后,看看后續(xù)aop是怎么和目標類結合的。
10.postProcessAfterInitialization細節(jié)
斷點已達。老辦法,看看是從哪調來的:
原來是這里,ioc創(chuàng)建完對象并給屬性賦完值之后。
回到postProcessAfterInitialization本身,就調了個wrapIfNecessary。邏輯都在里面了
10.1 找對應的增強器
打開斷點繼續(xù),先主要是個getAdvicesAndAdvisorsForBean然后調findEligibleAdvisors然后就是以前跑過的找事務略。然后主要是findAdvisorsThatCanApply(名字也看得出,它能用的 這個bean對應的切面),進去又是個canApply(candidate, clazz, hasIntroductions),這就是具體判斷了:
獲取所有方法,用匹配器match去匹配是否匹配上了
循環(huán)記下,全部找出來,找增強器就結束了!
10.2 織入生成代理對象
回到wrapIfNecessary開始創(chuàng)建代理對象了:
這里面框起來是涉及注解配置的,對應你配置的:
@EnableAspectJAutoProxy(exposeProxy = true)
@EnableAspectJAutoProxy(proxyTargetClass = true)
如果這兩個設置了的話,就會處理實現(xiàn)。
第二個是啟動優(yōu)先cglib,第一個是把代理對象創(chuàng)建好之后暴露出去,這樣就能讓原本this.dadd去調用方法本來不能增強的情況 可以用
((Calculate) AopContext.currentProxy()).add(numA,numB);也觸發(fā)增強效果
后面的話就是創(chuàng)建個代理工廠ProxyFactory,把增強器設置進去,最后調用getProxy
一路跳轉:
這就是最后網(wǎng)上背背背的東西了。在沒有接口和沒打優(yōu)先cglib的話用jdk創(chuàng)建否則cglib創(chuàng)建。
問題:
1.怎么得出來繼承結構哪些是重要的、哪些是不需要看不重要的
2.怎么整理出來的?