1、準備工做java
在這裏我先簡單記錄下如何實現一個aop:spring
AOP:【動態代理】 指在程序運行期間動態的將某段代碼切入到指定方法指定位置進行運行的編程方式; 一、導入aop模塊;Spring AOP:(spring-aspects) 二、定義一個業務邏輯類(MathCalculator);在業務邏輯運行的時候將日誌進行打印(方法以前、方法運行結束、方法出現異常,xxx) 三、定義一個日誌切面類(LogAspects):切面類裏面的方法須要動態感知MathCalculator.div運行到哪裏而後執行; 通知方法: 前置通知(@Before):logStart:在目標方法(div)運行以前運行 後置通知(@After):logEnd:在目標方法(div)運行結束以後運行(不管方法正常結束仍是異常結束) 返回通知(@AfterReturning):logReturn:在目標方法(div)正常返回以後運行 異常通知(@AfterThrowing):logException:在目標方法(div)出現異常之後運行 環繞通知(@Around):動態代理,手動推動目標方法運行(joinPoint.procced()) 四、給切面類的目標方法標註什麼時候何地運行(通知註解); 五、將切面類和業務邏輯類(目標方法所在類)都加入到容器中; 六、必須告訴Spring哪一個類是切面類(給切面類上加一個註解:@Aspect) 七、給配置類中加 @EnableAspectJAutoProxy 【開啓基於註解的aop模式】 在Spring中不少的 @EnableXXX; 三步: 1)、將業務邏輯組件和切面類都加入到容器中;告訴Spring哪一個是切面類(@Aspect) 2)、在切面類上的每個通知方法上標註通知註解,告訴Spring什麼時候何地運行(切入點表達式) 3)、開啓基於註解的aop模式;@EnableAspectJAutoProxy
我定義了一個除法方法,做爲一個切面:express
package com.kun.aop; public class MathCalculator { public int div(int i,int j){ System.out.println("MathCalculator...div..."); return i/j; } }
定義一個切面類:apache
package com.kun.aop; import java.util.Arrays; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; /** * 切面類 * @author lfy * * @Aspect: 告訴Spring當前類是一個切面類 * */ @Aspect public class LogAspects { //抽取公共的切入點表達式 //一、本類引用 //二、其餘的切面引用 @Pointcut("execution(public int com.kun.aop.MathCalculator.*(..))") public void pointCut(){}; //@Before在目標方法以前切入;切入點表達式(指定在哪一個方法切入) @Before("pointCut()") public void logStart(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); System.out.println(""+joinPoint.getSignature().getName()+"運行。。。@Before:參數列表是:{"+Arrays.asList(args)+"}"); } @After("com.kun.aop.LogAspects.pointCut()") public void logEnd(JoinPoint joinPoint){ System.out.println(""+joinPoint.getSignature().getName()+"結束。。。@After"); } //JoinPoint必定要出如今參數表的第一位 @AfterReturning(value="pointCut()",returning="result") public void logReturn(JoinPoint joinPoint,Object result){ System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:運行結果:{"+result+"}"); } @AfterThrowing(value="pointCut()",throwing="exception") public void logException(JoinPoint joinPoint,Exception exception){ System.out.println(""+joinPoint.getSignature().getName()+"異常。。。異常信息:{"+exception+"}"); } }
接下來是一個aop的配置:編程
package com.kun.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; import com.kun.aop.LogAspects; import com.kun.aop.MathCalculator; @EnableAspectJAutoProxy @Configuration public class MainConfigOfAOP { //業務邏輯類加入容器中 @Bean public MathCalculator calculator(){ return new MathCalculator(); } //切面類加入到容器中 @Bean public LogAspects logAspects(){ return new LogAspects(); } }
經過以上代碼咱們就完成了一個簡單的aop操做,接下來咱們根據源碼來探究一下springAOP的實現原理。數組
2、從@EnableAspectJAutoProxy看起緩存
查看一下@EnableAspectJAutoProxy的定義:app
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy { /** * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. The default is {@code false}. */ boolean proxyTargetClass() default false; }
咱們發現它導入了一個AspectJAutoProxyRegistrar組件,進一步查看其代碼:less
/* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.context.annotation; import org.springframework.aop.config.AopConfigUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.type.AnnotationMetadata; import static org.springframework.context.annotation.MetadataUtils.*; /** * Registers an {@link org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator * AnnotationAwareAspectJAutoProxyCreator} against the current {@link BeanDefinitionRegistry} * as appropriate based on a given @{@link EnableAspectJAutoProxy} annotation. * * @author Chris Beams * @see EnableAspectJAutoProxy * @since 3.1 */ class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar { /** * Register, escalate, and configure the AspectJ auto proxy creator based on the value * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing * {@code @Configuration} class. */ public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAJAutoProxy = attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } } }
咱們發現它實現了ImportBeanDefinitionRegistrar接口,這個接口能夠向IOC容器中註冊bean。 由此能夠推測aop利用AspectJAutoProxyRegistrar自定義給容器中註冊bean;BeanDefinetion。經過斷點咱們發現post
IOC容器中注入了一個internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator的bean,到此能夠得出結論,@EnableAspectJAutoProxy給容器中註冊一個AnnotationAwareAspectJAutoProxyCreator。
3、AnnotationAwareAspectJAutoProxyCreator建立過程
首先查看類圖:
在此須要關注兩點內容:
1)關注後置處理器SmartInstantiationAwareBeanPostProcessor(在bean初始化完成先後作事情)
2)關注自動裝配BeanFactory。
經過代碼查看,發現父類AbstractAutoProxyCreator中有後置處理器的內容;AbstactAdvisorAutoProxyCreator類中重寫了其父類AbstractAutoProxyCreator中setBeanFactory()方法,在AnnotationAwareAspectJAutoProxyCreator類中initBeanFactory()方法完成了自動裝配BeanFactory。分別在這兩處關注點打斷點來查看其流程:
/** * Instantiate and invoke all registered BeanPostProcessor beans, * respecting explicit order if given. * <p>Must be called before any instantiation of application beans. */ protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // Register BeanPostProcessorChecker that logs an info message when // a bean is created during BeanPostProcessor instantiation, i.e. when // a bean is not eligible for getting processed by all BeanPostProcessors. int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // Separate between BeanPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>(); List<String> orderedPostProcessorNames = new ArrayList<String>(); List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); for (String ppName : postProcessorNames) { if (isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, register the BeanPostProcessors that implement PriorityOrdered. OrderComparator.sort(priorityOrderedPostProcessors); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement Ordered. List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>(); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } OrderComparator.sort(orderedPostProcessors); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // Now, register all regular BeanPostProcessors. List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // Finally, re-register all internal BeanPostProcessors. OrderComparator.sort(internalPostProcessors); registerBeanPostProcessors(beanFactory, internalPostProcessors); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector()); }
總結以下:
1)、傳入配置類,建立ioc容器 2)、註冊配置類,調用refresh()刷新容器; 3)、registerBeanPostProcessors(beanFactory);註冊bean的後置處理器來方便攔截bean的建立; 1)、先獲取ioc容器已經定義了的須要建立對象的全部BeanPostProcessor 2)、給容器中加別的BeanPostProcessor 3)、優先註冊實現了PriorityOrdered接口的BeanPostProcessor; 4)、再給容器中註冊實現了Ordered接口的BeanPostProcessor; 5)、註冊沒實現優先級接口的BeanPostProcessor; 6)、註冊BeanPostProcessor,實際上就是建立BeanPostProcessor對象,保存在容器中; 建立internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】 1)、建立Bean的實例 2)、populateBean;給bean的各類屬性賦值 3)、initializeBean:初始化bean; 1)、invokeAwareMethods():處理Aware接口的方法回調 2)、applyBeanPostProcessorsBeforeInitialization():應用後置處理器的postProcessBeforeInitialization() 3)、invokeInitMethods();執行自定義的初始化方法 4)、applyBeanPostProcessorsAfterInitialization();執行後置處理器的postProcessAfterInitialization(); 4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)建立成功;--》aspectJAdvisorsBuilder 7)、把BeanPostProcessor註冊到BeanFactory中; beanFactory.addBeanPostProcessor(postProcessor);
=======以上是建立和註冊AnnotationAwareAspectJAutoProxyCreator的過程========
4、AnnotationAwareAspectJAutoProxyCreator的執行時機
經過以上步驟咱們發如今IOC容器啓動時候,會經過一個@EnableAspectJAutoProxy註解注入AnnotationAwareAspectJAutoProxyCreator對象,並分析了該對象在IOC容器的啓動時進行建立的過程。接下來咱們重點來分析一下AnnotationAwareAspectJProxyCreator對象執行的時機。
以前分析到AnnotationAwareAspectJAutoProxyCreator是一個後置處理器,能夠猜想它在其餘bean的初始化先後進行了特殊處理。我在它父類的postProcessBeforeInstantiation方法進行了斷點調試,其方法調用棧以下:
經過對方法棧中源碼的簡單查看,我繼續完善了流程:
流程: 1)、傳入配置類,建立ioc容器 2)、註冊配置類,調用refresh()刷新容器; 3)、registerBeanPostProcessors(beanFactory);註冊bean的後置處理器來方便攔截bean的建立; 1)、先獲取ioc容器已經定義了的須要建立對象的全部BeanPostProcessor 2)、給容器中加別的BeanPostProcessor 3)、優先註冊實現了PriorityOrdered接口的BeanPostProcessor; 4)、再給容器中註冊實現了Ordered接口的BeanPostProcessor; 5)、註冊沒實現優先級接口的BeanPostProcessor; 6)、註冊BeanPostProcessor,實際上就是建立BeanPostProcessor對象,保存在容器中; 建立internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】 1)、建立Bean的實例 2)、populateBean;給bean的各類屬性賦值 3)、initializeBean:初始化bean; 1)、invokeAwareMethods():處理Aware接口的方法回調 2)、applyBeanPostProcessorsBeforeInitialization():應用後置處理器的postProcessBeforeInitialization() 3)、invokeInitMethods();執行自定義的初始化方法 4)、applyBeanPostProcessorsAfterInitialization();執行後置處理器的postProcessAfterInitialization(); 4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)建立成功;--》aspectJAdvisorsBuilder 7)、把BeanPostProcessor註冊到BeanFactory中; beanFactory.addBeanPostProcessor(postProcessor); =======以上是建立和註冊AnnotationAwareAspectJAutoProxyCreator的過程======== AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor 4)、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工做;建立剩下的單實例bean 1)、遍歷獲取容器中全部的Bean,依次建立對象getBean(beanName); getBean->doGetBean()->getSingleton()-> 2)、建立bean 【AnnotationAwareAspectJAutoProxyCreator在全部bean建立以前會有一個攔截,InstantiationAwareBeanPostProcessor,
會調用postProcessBeforeInstantiation()】 1)、先從緩存中獲取當前bean,若是能獲取到,說明bean是以前被建立過的,直接使用,不然再建立; 只要建立好的Bean都會被緩存起來 2)、createBean();建立bean; AnnotationAwareAspectJAutoProxyCreator 會在任何bean建立以前先嚐試返回bean的實例 【BeanPostProcessor是在Bean對象建立完成初始化先後調用的】 【InstantiationAwareBeanPostProcessor是在建立Bean實例以前先嚐試用後置處理器返回對象的】 1)、resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation 但願後置處理器在此能返回一個代理對象;若是能返回代理對象就使用,若是不能就繼續 1)、後置處理器先嚐試返回對象; bean = applyBeanPostProcessorsBeforeInstantiation(): 拿到全部後置處理器,若是是InstantiationAwareBeanPostProcessor; 就執行postProcessBeforeInstantiation if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } 2)、doCreateBean(beanName, mbdToUse, args);真正的去建立一個bean實例;和3.6流程同樣; 3)、
5、建立AOP代理
上一步我發現AnnotationAwareAspectJAutoProxyCreator在全部bean建立時進行了攔截,執行其中的postProcessBeforeInstantiation方法,接下來咱們繼續經過斷點調試查看該方法的進行的操做。
首先方法內部會進行一系列的判斷,判斷當前bean是否在advisedBeans中(保存了全部須要加強bean)、判斷當前bean是不是基礎類型的Advice、Pointcut、Advisor、AopInfrastructureBean、判斷是不是切面(是否實現了註解@Aspect)、判斷是否須要跳過等。
在判斷的過程當中會拿到加強bean的相關的通知方法,並經過這些切面進行邏輯判斷。
執行完postProcessBeforeInstantiation方法進行通知方法的判斷後,執行postProcessAfterInitialization方法。
咱們發現postProcessAfterInitialization方法會對切面進行一次包裝的處理。
在對對象包裝的過程當中建立了一個代理對象。
咱們細看建立代理對象的過程,發如今建立以前首先會根據切入點表達式對加強器進行一一匹配,最終拿到全部的加強器。
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { if (this.beanFactory instanceof ConfigurableListableBeanFactory) { AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass); } ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (this.shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { this.evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); this.customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (this.advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(this.getProxyClassLoader()); }
建立代理對象過程當中,會先建立一個代理工廠,獲取到全部的加強器(通知方法),將這些加強器和目標類注入代理工廠,再用代理工廠建立對象。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) { return new JdkDynamicAopProxy(config); } else { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation."); } else { return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config)); } } }
代理工廠會選擇JdkDynamicAopProxy或者CglibAopProxy,主要經過是否接口和是否配置cglib代理來選擇。最終工廠會建立一個代理加強的對象。咱們繼續完善以前的流程.。
流程: 1)、傳入配置類,建立ioc容器 2)、註冊配置類,調用refresh()刷新容器; 3)、registerBeanPostProcessors(beanFactory);註冊bean的後置處理器來方便攔截bean的建立; 1)、先獲取ioc容器已經定義了的須要建立對象的全部BeanPostProcessor 2)、給容器中加別的BeanPostProcessor 3)、優先註冊實現了PriorityOrdered接口的BeanPostProcessor; 4)、再給容器中註冊實現了Ordered接口的BeanPostProcessor; 5)、註冊沒實現優先級接口的BeanPostProcessor; 6)、註冊BeanPostProcessor,實際上就是建立BeanPostProcessor對象,保存在容器中; 建立internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】 1)、建立Bean的實例 2)、populateBean;給bean的各類屬性賦值 3)、initializeBean:初始化bean; 1)、invokeAwareMethods():處理Aware接口的方法回調 2)、applyBeanPostProcessorsBeforeInitialization():應用後置處理器的postProcessBeforeInitialization() 3)、invokeInitMethods();執行自定義的初始化方法 4)、applyBeanPostProcessorsAfterInitialization();執行後置處理器的postProcessAfterInitialization(); 4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)建立成功;--》aspectJAdvisorsBuilder 7)、把BeanPostProcessor註冊到BeanFactory中; beanFactory.addBeanPostProcessor(postProcessor); =======以上是建立和註冊AnnotationAwareAspectJAutoProxyCreator的過程======== AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor 4)、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工做;建立剩下的單實例bean 1)、遍歷獲取容器中全部的Bean,依次建立對象getBean(beanName); getBean->doGetBean()->getSingleton()-> 2)、建立bean 【AnnotationAwareAspectJAutoProxyCreator在全部bean建立以前會有一個攔截,InstantiationAwareBeanPostProcessor, 會調用postProcessBeforeInstantiation()】 1)、先從緩存中獲取當前bean,若是能獲取到,說明bean是以前被建立過的,直接使用,不然再建立; 只要建立好的Bean都會被緩存起來 2)、createBean();建立bean; AnnotationAwareAspectJAutoProxyCreator 會在任何bean建立以前先嚐試返回bean的實例 【BeanPostProcessor是在Bean對象建立完成初始化先後調用的】 【InstantiationAwareBeanPostProcessor是在建立Bean實例以前先嚐試用後置處理器返回對象的】 1)、resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation 但願後置處理器在此能返回一個代理對象;若是能返回代理對象就使用,若是不能就繼續 1)、後置處理器先嚐試返回對象; bean = applyBeanPostProcessorsBeforeInstantiation(): 拿到全部後置處理器,若是是InstantiationAwareBeanPostProcessor; 就執行postProcessBeforeInstantiation if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } 2)、doCreateBean(beanName, mbdToUse, args);真正的去建立一個bean實例;和3.6流程同樣; 3)、 AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】 的做用: 1)、每個bean建立以前,調用postProcessBeforeInstantiation(); 關心MathCalculator和LogAspect的建立 1)、判斷當前bean是否在advisedBeans中(保存了全部須要加強bean) 2)、判斷當前bean是不是基礎類型的Advice、Pointcut、Advisor、AopInfrastructureBean, 或者是不是切面(@Aspect) 3)、是否須要跳過 1)、獲取候選的加強器(切面裏面的通知方法)【List<Advisor> candidateAdvisors】 每個封裝的通知方法的加強器是 InstantiationModelAwarePointcutAdvisor; 判斷每個加強器是不是 AspectJPointcutAdvisor 類型的;返回true 2)、永遠返回false 2)、建立對象 postProcessAfterInitialization; return wrapIfNecessary(bean, beanName, cacheKey);//包裝若是須要的狀況下 1)、獲取當前bean的全部加強器(通知方法) Object[] specificInterceptors 一、找到候選的全部的加強器(找哪些通知方法是須要切入當前bean方法的) 二、獲取到能在bean使用的加強器。 三、給加強器排序 2)、保存當前bean在advisedBeans中; 3)、若是當前bean須要加強,建立當前bean的代理對象; 1)、獲取全部加強器(通知方法) 2)、保存到proxyFactory 3)、建立代理對象:Spring自動決定 JdkDynamicAopProxy(config);jdk動態代理; ObjenesisCglibAopProxy(config);cglib的動態代理; 4)、給容器中返回當前組件使用cglib加強了的代理對象; 5)、之後容器中獲取到的就是這個組件的代理對象,執行目標方法的時候,代理對象就會執行通知方法的流程;
6、獲取攔截器鏈
上一步分析了目標方法被代理並建立的過程,接下來咱們分析目標方法被攔截並執行的過程。
由於要查看目標方法的執行過程,因此我繼續在目標方法上進行斷點調試。經過對MathCalculator查看,能夠發現它從IOC容器中取出已是一個cglib代理對象了,其中包含加強方法和目標對象的一些詳細信息。
緊接着斷點進入CglibAopProxy.intercept()攔截器,其中會獲取即將執行的目標方法的攔截器鏈。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice( Advised config, Method method, Class targetClass) { // This is somewhat tricky... we have to process introductions first, // but we need to preserve order in the ultimate list. List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length); boolean hasIntroductions = hasMatchingIntroductions(config, targetClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); for (Advisor advisor : config.getAdvisors()) { if (advisor instanceof PointcutAdvisor) { // Add it conditionally. PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) { MethodInterceptor[] interceptors = registry.getInterceptors(advisor); MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) { if (mm.isRuntime()) { // Creating a new object instance in the getInterceptors() method // isn't a problem as we normally cache created chains. for (MethodInterceptor interceptor : interceptors) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } else if (advisor instanceof IntroductionAdvisor) { IntroductionAdvisor ia = (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } return interceptorList; }
經過registry.getInterceptors(advisor)方法獲取全部的加強器,並將加強器轉爲List<MethodInterceptor>,最終返回。
public Object proceed() throws Throwable { if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return this.invokeJoinpoint(); } else { Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice; return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed(); } else { return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this); } } }
以後,會將攔截器鏈和目標對象等傳入methodInvocation,並調用proceed()方法。該方法執行也是攔截器的觸發過程,也是目標方法的主要執行過程。
經過索引遍歷攔截器鏈中的全部的攔截器(封裝的加強器),並分別執行加強方法。每次執行攔截器方法索引自增,直至全部的加強方法執行完畢。
源碼中有一個ExposeInvocationInterceptor對象會將MethodInvocation放入到ThreadLocal進行線程共享,查看相關資料說方便同一線程中其餘地方獲取通知方法,具體哪裏得到,我暫時沒有找到,在後續工做學習中繼續深刻查看探究吧。
完善流程以下:
流程: 1)、傳入配置類,建立ioc容器 2)、註冊配置類,調用refresh()刷新容器; 3)、registerBeanPostProcessors(beanFactory);註冊bean的後置處理器來方便攔截bean的建立; 1)、先獲取ioc容器已經定義了的須要建立對象的全部BeanPostProcessor 2)、給容器中加別的BeanPostProcessor 3)、優先註冊實現了PriorityOrdered接口的BeanPostProcessor; 4)、再給容器中註冊實現了Ordered接口的BeanPostProcessor; 5)、註冊沒實現優先級接口的BeanPostProcessor; 6)、註冊BeanPostProcessor,實際上就是建立BeanPostProcessor對象,保存在容器中; 建立internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】 1)、建立Bean的實例 2)、populateBean;給bean的各類屬性賦值 3)、initializeBean:初始化bean; 1)、invokeAwareMethods():處理Aware接口的方法回調 2)、applyBeanPostProcessorsBeforeInitialization():應用後置處理器的postProcessBeforeInitialization() 3)、invokeInitMethods();執行自定義的初始化方法 4)、applyBeanPostProcessorsAfterInitialization();執行後置處理器的postProcessAfterInitialization(); 4)、BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)建立成功;--》aspectJAdvisorsBuilder 7)、把BeanPostProcessor註冊到BeanFactory中; beanFactory.addBeanPostProcessor(postProcessor); =======以上是建立和註冊AnnotationAwareAspectJAutoProxyCreator的過程======== AnnotationAwareAspectJAutoProxyCreator => InstantiationAwareBeanPostProcessor 4)、finishBeanFactoryInitialization(beanFactory);完成BeanFactory初始化工做;建立剩下的單實例bean 1)、遍歷獲取容器中全部的Bean,依次建立對象getBean(beanName); getBean->doGetBean()->getSingleton()-> 2)、建立bean 【AnnotationAwareAspectJAutoProxyCreator在全部bean建立以前會有一個攔截,InstantiationAwareBeanPostProcessor, 會調用postProcessBeforeInstantiation()】 1)、先從緩存中獲取當前bean,若是能獲取到,說明bean是以前被建立過的,直接使用,不然再建立; 只要建立好的Bean都會被緩存起來 2)、createBean();建立bean; AnnotationAwareAspectJAutoProxyCreator 會在任何bean建立以前先嚐試返回bean的實例 【BeanPostProcessor是在Bean對象建立完成初始化先後調用的】 【InstantiationAwareBeanPostProcessor是在建立Bean實例以前先嚐試用後置處理器返回對象的】 1)、resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation 但願後置處理器在此能返回一個代理對象;若是能返回代理對象就使用,若是不能就繼續 1)、後置處理器先嚐試返回對象; bean = applyBeanPostProcessorsBeforeInstantiation(): 拿到全部後置處理器,若是是InstantiationAwareBeanPostProcessor; 就執行postProcessBeforeInstantiation if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } 2)、doCreateBean(beanName, mbdToUse, args);真正的去建立一個bean實例;和3.6流程同樣; 3)、 AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】 的做用: 1)、每個bean建立以前,調用postProcessBeforeInstantiation(); 關心MathCalculator和LogAspect的建立 1)、判斷當前bean是否在advisedBeans中(保存了全部須要加強bean) 2)、判斷當前bean是不是基礎類型的Advice、Pointcut、Advisor、AopInfrastructureBean, 或者是不是切面(@Aspect) 3)、是否須要跳過 1)、獲取候選的加強器(切面裏面的通知方法)【List<Advisor> candidateAdvisors】 每個封裝的通知方法的加強器是 InstantiationModelAwarePointcutAdvisor; 判斷每個加強器是不是 AspectJPointcutAdvisor 類型的;返回true 2)、永遠返回false 2)、建立對象 postProcessAfterInitialization; return wrapIfNecessary(bean, beanName, cacheKey);//包裝若是須要的狀況下 1)、獲取當前bean的全部加強器(通知方法) Object[] specificInterceptors 一、找到候選的全部的加強器(找哪些通知方法是須要切入當前bean方法的) 二、獲取到能在bean使用的加強器。 三、給加強器排序 2)、保存當前bean在advisedBeans中; 3)、若是當前bean須要加強,建立當前bean的代理對象; 1)、獲取全部加強器(通知方法) 2)、保存到proxyFactory 3)、建立代理對象:Spring自動決定 JdkDynamicAopProxy(config);jdk動態代理; ObjenesisCglibAopProxy(config);cglib的動態代理; 4)、給容器中返回當前組件使用cglib加強了的代理對象; 5)、之後容器中獲取到的就是這個組件的代理對象,執行目標方法的時候,代理對象就會執行通知方法的流程; 3)、目標方法執行 ;
容器中保存了組件的代理對象(cglib加強後的對象),這個對象裏面保存了詳細信息(好比加強器,目標對象,xxx); 1)、CglibAopProxy.intercept();攔截目標方法的執行 2)、根據ProxyFactory對象獲取將要執行的目標方法攔截器鏈; List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 1)、List<Object> interceptorList保存全部攔截器 5 一個默認的ExposeInvocationInterceptor 和 4個加強器; 2)、遍歷全部的加強器,將其轉爲Interceptor; registry.getInterceptors(advisor); 3)、將加強器轉爲List<MethodInterceptor>; 若是是MethodInterceptor,直接加入到集合中 若是不是,使用AdvisorAdapter將加強器轉爲MethodInterceptor; 轉換完成返回MethodInterceptor數組;
3)、若是沒有攔截器鏈,直接執行目標方法;
攔截器鏈(每個通知方法又被包裝爲方法攔截器,利用MethodInterceptor機制)
4)、若是有攔截器鏈,把須要執行的目標對象,目標方法,
攔截器鏈等信息傳入建立一個 CglibMethodInvocation 對象,
並調用 Object retVal = mi.proceed();
5)、攔截器鏈的觸發過程;
1)、若是沒有攔截器執行執行目標方法,或者攔截器的索引和攔截器數組-1大小同樣(指定到了最後一個攔截器)執行目標方法;
2)、鏈式獲取每個攔截器,攔截器執行invoke方法,每個攔截器等待下一個攔截器執行完成返回之後再來執行;
攔截器鏈的機制,保證通知方法與目標方法的執行順序;
7、小結