AOP原理解读
AOP(動態(tài)代理):指在程序運行期間動態(tài)的將某段代碼切入到指定方法或指定位置中進行運行。
切面類上加@Aspect注解? 配置類上加@EnableAspectAutoProxy
通知方法:前置通知(@Before),后置通知(@After),返回通知(@AfterReturning),異常通知(@AfterThrowing)
源碼解讀:
1.@EnableAspectJautoProxy
? ? ? ? ??@Import(AspectJAutoProxyRegistrar.class)
? ? ? ? ? ?利用AspectJAutoProxyRegistrar自定義給容器中注冊bean。
? ? ? ? ? ? 注冊了一個AnnotationAwareAspectJAutoProxyCreator組件。
2.AnnotationAwareAspectJAutoProxyCreator的作用
繼承關(guān)系:
AnnotationAwareAspectJAutoProxyCreator:
?? ? ?AnnotationAwareAspectJAutoProxyCreator
?? ? ? ? ? ->AspectJAwareAdvisorAutoProxyCreator
?? ? ? ? ? ? ? ? ? ->AbstractAdvisorAutoProxyCreator
?? ? ? ? ? ? ? ? ? ? ? ? ? ?->AbstractAutoProxyCreator??implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
------------------------------概括以上內(nèi)容:定義了一個后置處理器---------------------------------------------------------------------
在IOC容器創(chuàng)建過程中關(guān)于后置處理器的操作:
?* ?? ??? ?1)、傳入配置類,創(chuàng)建ioc容器
?* ?? ??? ?2)、注冊配置類,調(diào)用refresh()刷新容器;
?* ?? ??? ?3)、registerBeanPostProcessors(beanFactory);注冊bean的后置處理器來方便攔截bean的創(chuàng)建;
?* ?? ??? ??? ?1)、先獲取ioc容器已經(jīng)定義了的需要創(chuàng)建對象的所有BeanPostProcessor(上面定義了一個后置處理器)
?* ?? ??? ??? ?2)、給容器中加別的BeanPostProcessor
?* ?? ??? ??? ?3)、優(yōu)先注冊實現(xiàn)了PriorityOrdered接口的BeanPostProcessor;
?* ?? ??? ??? ?4)、再給容器中注冊實現(xiàn)了Ordered接口的BeanPostProcessor;
?* ?? ??? ??? ?5)、注冊沒實現(xiàn)優(yōu)先級接口的BeanPostProcessor;
?* ?? ??? ??? ?6)、注冊BeanPostProcessor,實際上就是創(chuàng)建BeanPostProcessor對象,保存在容器中;
?* ?? ??? ??? ??? ?創(chuàng)建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】
?* ?? ??? ??? ??? ?1)、創(chuàng)建Bean的實例
?* ?? ??? ??? ??? ?2)、populateBean;給bean的各種屬性賦值
?* ?? ??? ??? ??? ?3)、initializeBean:初始化bean;
?* ?? ??? ??? ??? ??? ??? ?1)、invokeAwareMethods():處理Aware接口的方法回調(diào)
?* ?? ??? ??? ??? ??? ??? ?2)、applyBeanPostProcessorsBeforeInitialization():應(yīng)用后置處理器的postProcessBeforeInitialization()
?* ?? ??? ??? ??? ??? ??? ?3)、invokeInitMethods();執(zhí)行自定義的初始化方法
?* ?? ??? ??? ??? ??? ??? ?4)、applyBeanPostProcessorsAfterInitialization();執(zhí)行后置處理器的postProcessAfterInitialization();
?* ?? ??? ??? ??? ?4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)創(chuàng)建成功;--》aspectJAdvisorsBuilder
?* ?? ??? ??? ?7)、把BeanPostProcessor注冊到BeanFactory中;
?* ?? ??? ??? ??? ?beanFactory.addBeanPostProcessor(postProcessor);
?* -------------------概括以上內(nèi)容:創(chuàng)建和注冊AnnotationAwareAspectJAutoProxyCreator的過程-------------------
現(xiàn)在后置處理器注冊到了容器中了,那么如何起作用?
?
? ? ? 4)、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工作;創(chuàng)建剩下的單實例bean
?* ?? ??? ??? ?1)、遍歷獲取容器中所有的Bean,依次創(chuàng)建對象getBean(beanName);
?* ?? ??? ??? ??? ?getBean->doGetBean()->getSingleton()->
?* ?? ??? ??? ?2)、創(chuàng)建bean
?*? ? ? ? ? ? ? ? ?
?* ?? ??? ??? ??? ?1)、先從緩存中獲取當(dāng)前bean,如果能獲取到,說明bean是之前被創(chuàng)建過的,直接使用,否則再創(chuàng)建;
?* ?? ??? ??? ??? ??? ?只要創(chuàng)建好的Bean都會被緩存起來
?* ?? ??? ??? ??? ?2)、createBean();創(chuàng)建bean;
?* ?? ??? ??? ??? ??? ?AnnotationAwareAspectJAutoProxyCreator(他的父類是InstantiationAwareBeanPostProcessor)
? ? ? ? ? ? ? ? ? ? ? ?會在任何bean創(chuàng)建之前先嘗試返回bean的實例
? ? ? ? ? ? ? ? ? ? ? ? ? (倆種后置處理器
?* ?? ??? ??? ??? ??? ?【BeanPostProcessor是在Bean對象創(chuàng)建完成初始化前后調(diào)用的】? ? ?
?* ?? ??? ??? ??? ??? ?【InstantiationAwareBeanPostProcessor是在創(chuàng)建Bean實例之前先嘗試用后置處理器返回對象的】?)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1)、resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation
?*? ? ? ? ? ? ? ? ? ? ? ? ? ?希望后置處理器在此能返回一個代理對象;如果能返回代理對象就使用,如果不能就繼續(xù)
?*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 1)、后置處理器先嘗試返回對象;
?*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?bean = applyBeanPostProcessorsBeforeInstantiation():
?*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 拿到所有后置處理器,如果是InstantiationAwareBeanPostProcessor;(上文定義
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?并注冊的后置處理器就是此類型)
?*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 就執(zhí)行bean=postProcessBeforeInstantiation()
?*? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (bean != null) {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??2)、如果上面沒有獲得bean就按照正常流程創(chuàng)建bean。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?doCreateBean(beanName, mbdToUse,args);真正的去創(chuàng)建一個bean實例;和3.6流程一樣;
--------------------以上內(nèi)容講述了后置處理器 處理時機----------------------------------------
postProcessBeforeInstantiation() 和applyBeanPostProcessorsAfterInitialization() 作用
?
1)、每一個bean創(chuàng)建之前,調(diào)用postProcessBeforeInstantiation();
?* ?? ??? ?關(guān)心MathCalculator和LogAspect的創(chuàng)建
?* ?? ??? ?1)、判斷當(dāng)前bean是否在advisedBeans中(保存了所有需要增強bean)
?* ?? ??? ?2)、判斷當(dāng)前bean是否是基礎(chǔ)類型的Advice、Pointcut、Advisor、AopInfrastructureBean,
?* ?? ??? ??? ?或者是否是切面(@Aspect)
?* ?? ??? ?3)、是否需要跳過
?* ?? ??? ??? ?1)、獲取候選的增強器(切面里面的通知方法)【List<Advisor> candidateAdvisors】
?* ?? ??? ??? ??? ?每一個封裝的通知方法的增強器是 InstantiationModelAwarePointcutAdvisor;
?* ?? ??? ??? ??? ?判斷每一個增強器是否是 AspectJPointcutAdvisor 類型的;返回true
?* ?? ??? ??? ?2)、永遠返回false
?*?
?* 2)、?postProcessAfterInitialization;
?* ?? ??? ?return wrapIfNecessary(bean, beanName, cacheKey);//包裝如果需要的情況下
?* ?? ??? ?1)、獲取當(dāng)前bean的所有增強器(通知方法) ?Object[] ?specificInterceptors
?* ?? ??? ??? ?1、找到候選的所有的增強器(找哪些通知方法是需要切入當(dāng)前bean方法的)
?* ?? ??? ??? ?2、獲取到能在bean使用的增強器。
?* ?? ??? ??? ?3、給增強器排序
?* ?? ??? ?2)、保存當(dāng)前bean在advisedBeans中;
?* ?? ??? ?3)、如果當(dāng)前bean需要增強,創(chuàng)建當(dāng)前bean的代理對象;
?* ?? ??? ??? ?1)、獲取所有增強器(通知方法)
?* ?? ??? ??? ?2)、保存到proxyFactory
?* ?? ??? ??? ?3)、創(chuàng)建代理對象:Spring自動決定
?* ?? ??? ??? ??? ?JdkDynamicAopProxy(config);jdk動態(tài)代理;
?* ?? ??? ??? ??? ?ObjenesisCglibAopProxy(config);cglib的動態(tài)代理;
?* ?? ??? ?4)、給容器中返回當(dāng)前組件使用cglib增強了的代理對象;
?* ?? ??? ?5)、以后容器中獲取到的就是這個組件的代理對象,執(zhí)行目標方法的時候,代理對象就會執(zhí)行通知方法的流程;
?
目標方法執(zhí)行;
?* ?? ??? ?容器中保存了組件的代理對象(cglib增強后的對象),這個對象里面保存了詳細信息(比如增強器,目標對象,xxx);
?* ?? ??? ?1)、CglibAopProxy.intercept();攔截目標方法的執(zhí)行
?* ?? ??? ?2)、根據(jù)ProxyFactory對象獲取將要執(zhí)行的目標方法攔截器鏈;
?* ?? ??? ??? ?List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
?* ?? ??? ??? ?1)、List<Object> interceptorList保存所有攔截器,長度為 5,有一個默認的。
?* ?? ??? ??? ??? ?一個默認的ExposeInvocationInterceptor 和 4個增強器;
?* ?? ??? ??? ?2)、遍歷所有的增強器,將其轉(zhuǎn)為Interceptor;
?* ?? ??? ??? ??? ?registry.getInterceptors(advisor);
?* ?? ??? ??? ?3)、將增強器轉(zhuǎn)為List<MethodInterceptor>;
?* ?? ??? ??? ??? ?如果是MethodInterceptor,直接加入到集合中
?* ?? ??? ??? ??? ?如果不是,使用AdvisorAdapter將增強器轉(zhuǎn)為MethodInterceptor;
?* ?? ??? ??? ??? ?轉(zhuǎn)換完成返回MethodInterceptor數(shù)組;
?*?
?* ?? ??? ?3)、如果沒有攔截器鏈,直接執(zhí)行目標方法;
?* ?? ??? ??? ?攔截器鏈(每一個通知方法又被包裝為方法攔截器,利用MethodInterceptor機制)
?* ?? ??? ?4)、如果有攔截器鏈,把需要執(zhí)行的目標對象,目標方法,
?* ?? ??? ??? ?攔截器鏈等信息傳入創(chuàng)建一個 CglibMethodInvocation 對象,
?* ?? ??? ??? ?并調(diào)用 Object retVal = ?mi.proceed();
?* ?? ??? ?5)、攔截器鏈的觸發(fā)過程;
?* ?? ??? ??? ?1)、如果沒有攔截器執(zhí)行執(zhí)行目標方法,或者攔截器的索引和攔截器數(shù)組-1大小一樣(指定到了最后一個攔截器)執(zhí)行目標方法;
?* ?? ??? ??? ?2)、鏈式獲取每一個攔截器,攔截器執(zhí)行invoke方法,每一個攔截器等待下一個攔截器執(zhí)行完成返回以后再來執(zhí)行;
?* ?? ??? ??? ??? ?攔截器鏈的機制,保證通知方法與目標方法的執(zhí)行順序;
?* ??
? ? ?總結(jié)
?* ?? ??? ?1)、 ?@EnableAspectJAutoProxy 開啟AOP功能
?* ?? ??? ?2)、 @EnableAspectJAutoProxy 會給容器中注冊一個組件 AnnotationAwareAspectJAutoProxyCreator
?* ?? ??? ?3)、AnnotationAwareAspectJAutoProxyCreator是一個后置處理器;
?* ?? ??? ?4)、容器的創(chuàng)建流程:
?* ?? ??? ??? ?1)、registerBeanPostProcessors()注冊后置處理器;創(chuàng)建AnnotationAwareAspectJAutoProxyCreator對象
?* ?? ??? ??? ?2)、finishBeanFactoryInitialization()初始化剩下的單實例bean
?* ?? ??? ??? ??? ?1)、創(chuàng)建業(yè)務(wù)邏輯組件和切面組件
?* ?? ??? ??? ??? ?2)、AnnotationAwareAspectJAutoProxyCreator攔截組件的創(chuàng)建過程
?* ?? ??? ??? ??? ?3)、組件創(chuàng)建完之后,判斷組件是否需要增強
?* ?? ??? ??? ??? ??? ?是:切面的通知方法,包裝成增強器(Advisor);給業(yè)務(wù)邏輯組件創(chuàng)建一個代理對象(cglib);
?* ?? ??? ?5)、執(zhí)行目標方法:
?* ?? ??? ??? ?1)、代理對象執(zhí)行目標方法
?* ?? ??? ??? ?2)、CglibAopProxy.intercept();
?* ?? ??? ??? ??? ?1)、得到目標方法的攔截器鏈(增強器包裝成攔截器MethodInterceptor)
?* ?? ??? ??? ??? ?2)、利用攔截器的鏈式機制,依次進入每一個攔截器進行執(zhí)行;
?* ?? ??? ??? ??? ?3)、效果:
?* ?? ??? ??? ??? ??? ?正常執(zhí)行:前置通知-》目標方法-》后置通知-》返回通知
?* ?? ??? ??? ??? ??? ?出現(xiàn)異常:前置通知-》目標方法-》后置通知-》異常通知
?* ?? ??? ?
總結(jié)
- 上一篇: java虚拟机的俩种异常
- 下一篇: @EnableTransactionMa