spring系列-注解驱动原理及源码-AOP使用及源码解析
目錄
一、用注解方式開啟AOP
1、實(shí)例
2、AOP簡(jiǎn)單小結(jié)
二、AOP原理
1、@EnableAspectJAutoProxy溯源
2、AnnotationAwareAspectJAutoProxyCreator繼承體系深入研究
3、創(chuàng)建AOP代理
4、目標(biāo)對(duì)象的目標(biāo)方法執(zhí)行流程(攔截器鏈獲取)
5、攔截器鏈的觸發(fā)過程
三、AOP總結(jié)
1.AOP小結(jié)
一、用注解方式開啟AOP
1、實(shí)例
(1)pom導(dǎo)入AOP模塊
<!--AOP--> <dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>4.3.12.RELEASE</version> </dependency>(2)定義業(yè)務(wù)邏輯類(MathCalculator)
package com.xiang.spring.aop;public class MathCalculator {public int div(int i, int j) {return i/j;} }(3)定義日志切面類(LogAspect)
package com.xiang.spring.aop;import jdk.nashorn.internal.scripts.JO; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*;import java.util.Arrays;// 告訴spring,當(dāng)前類是一個(gè)切面類 @Aspect public class LogAspect {/*** aspect表達(dá)式:為MathCalculator類的任意方法:public int com.xiang.spring.aop.MathCalculator.*(..)* 抽取公共的切入點(diǎn)表達(dá)式* 如果在本類引用,直接寫方法名即可:@Before("pointCurt()")* 其他的切面引用,需要寫方法的全名*/@Pointcut("execution(public int com.xiang.spring.aop.MathCalculator.div(int, int))")public void pointCurt() {}/*** 前置通知(@Before):logStart:在目標(biāo)方法運(yùn)行之前運(yùn)行**/@Before("pointCurt()")public void logStart(JoinPoint joinPoint) {String name = joinPoint.getSignature().getName();// 方法名Object[] args = joinPoint.getArgs();// 參數(shù)列表System.out.println(name + "除法運(yùn)行。。。參數(shù)列表是" + Arrays.asList(args));}/*** 后置通知(@After):logEnd:在目標(biāo)方法運(yùn)行結(jié)束之后運(yùn)行* 無論方法是正常結(jié)束還是異常結(jié)束*/@After("pointCurt()")public void logEnd(JoinPoint joinPoint) {System.out.println("除法結(jié)束。。。");}/*** JoinPoint 參數(shù)一定要出現(xiàn)在參數(shù)表的第一位,否則會(huì)出錯(cuò)*/@AfterReturning(value = "pointCurt()", returning = "result")public void logReturn(JoinPoint joinPoint, Object result) {// 獲取方法返回值System.out.println("除法正常返回。。。運(yùn)行計(jì)算結(jié)果" + result);}@AfterThrowing(value = "pointCurt()", throwing = "exception")public void logException(JoinPoint joinPoint, Exception exception) {System.out.println("除法異常。。。異常信息" + exception);}/*** 環(huán)繞通知,返回Object類型*/@Around("pointCurt()")public Object logAround(ProceedingJoinPoint pjp) {Object rtValue = null;try {Object[] args = pjp.getArgs();// 執(zhí)行前置通知System.out.println("logAround before");rtValue = pjp.proceed(args); // 執(zhí)行攔截方法// 執(zhí)行后置通知System.out.println("logAround after");} catch (Throwable e) {// 執(zhí)行異常通知System.out.println("logAround error");} finally {// 執(zhí)行最終通知System.out.println("logAround finally");}return rtValue;} }(4)定義配置類
@EnableAspectJAutoProxy @Configuration public class MainConfigOfAOP {// 業(yè)務(wù)邏輯類加入容器中@Beanpublic MathCalculator mathCalculator() {return new MathCalculator();}// 切面類加入容器中@Beanpublic LogAspect logAspect() {return new LogAspect();} }(5)創(chuàng)建測(cè)試類
import com.xiang.spring.aop.MathCalculator; import com.xiang.spring.config.MainConfigOfAOP; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class IOCTest_AOP {@Testpublic void test01() {// 創(chuàng)建ioc容器,容器創(chuàng)建時(shí),默認(rèn)會(huì)將單例的bean都創(chuàng)建出來AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);System.out.println(mathCalculator.div(2, 1));System.out.println(mathCalculator.div(2, 0));} }// 執(zhí)行結(jié)果 div除法運(yùn)行。。。參數(shù)列表是[2, 1] 除法結(jié)束。。。 除法正常返回。。。運(yùn)行計(jì)算結(jié)果2 2 div除法運(yùn)行。。。參數(shù)列表是[2, 0] 除法結(jié)束。。。 除法異常。。。異常信息java.lang.ArithmeticException: / by zerojava.lang.ArithmeticException: / by zero2、AOP簡(jiǎn)單小結(jié)
AOP:【動(dòng)態(tài)代理】
?????指在程序運(yùn)行期間動(dòng)態(tài)的將某段代碼切入到指定方法指定位置進(jìn)行運(yùn)行的編程方式
(1).導(dǎo)入AOP模塊-(spring-aspects)
(2).定義業(yè)務(wù)邏輯類(MathCalculator):在業(yè)務(wù)邏輯運(yùn)行的時(shí)候,將日志進(jìn)行打印(方法之前、方法執(zhí)行后、方法出現(xiàn)異常時(shí))。
(3).定義一個(gè)日志切面類(LogAspect):切面類里面的方法需要?jiǎng)討B(tài)感知MathCalculator.div運(yùn)行到哪里,然后執(zhí)行。
?????通知方法:
?????????前置通知(@Before):logStart:在目標(biāo)方法運(yùn)行之前運(yùn)行
?????????后置通知(@After):logEnd:在目標(biāo)方法運(yùn)行結(jié)束之后運(yùn)行
?????????返回通知(@AfterReturning):logReturn:在目標(biāo)方法正常返回之后運(yùn)行
?????????異常通知(@AfterThrowing):logException:在目標(biāo)方法運(yùn)行出現(xiàn)異常之后運(yùn)行
?????????環(huán)繞通知(@Around):動(dòng)態(tài)代理,手動(dòng)推進(jìn)目標(biāo)方法運(yùn)行(joinPoint.proced)
(4).給切面類目標(biāo)方法標(biāo)注何時(shí)何地運(yùn)行(通知注解)
(5).將切面類和目標(biāo)業(yè)務(wù)邏輯類(目標(biāo)方法所在類),都加入到容器中。
(6).必須告訴spring,哪個(gè)類是切面類。給切面類上加一個(gè)注解@Aspect
(7).在配置類中加@EnableAspectJAutoProxy,啟用基于注解的aop模式。
?????在spring中,有很多的@EnableXxxxx,是開啟某個(gè)功能注解。
總體來說分三步:
?????1.業(yè)務(wù)邏輯組件和切面類都加入到容器中;告訴Spring哪個(gè)是切面類(@Aspect)。
?????2.在切面類上每個(gè)通知方法上都標(biāo)注通知注解,告訴spring何時(shí)何地運(yùn)行(寫好切入點(diǎn)表達(dá)式)。
?????3.開啟基于注解的AOP模式(@EnableAspectJAutoProxy)。
二、AOP原理
1、@EnableAspectJAutoProxy溯源
(1)@EnableAspectJAutoProxy導(dǎo)入了AspectJAutoProxyRegistrar組件
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Import(AspectJAutoProxyRegistrar.class) public @interface EnableAspectJAutoProxy {(2)AspectJAutoProxyRegistrar組件源碼
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.*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);AnnotationAttributes enableAspectJAutoProxy =AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}} }我們可以看到有一行代碼AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
利用AspectJAutoProxyRegistrar自定義給容器中注冊(cè)bean。
點(diǎn)進(jìn)去可以看到,實(shí)際是給容器中注冊(cè)一個(gè)組件名稱為internalAutoProxyCreator,組件類型為AnnotationAwareAspectJAutoProxyCreator(自動(dòng)代理創(chuàng)建器)的組件。
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition; }(3)AnnotationAwareAspectJAutoProxyCreator的繼承體系
AnnotationAwareAspectJAutoProxyCreatorextends AspectJAwareAdvisorAutoProxyCreatorextends AbstractAdvisorAutoProxyCreatorextends AbstractAutoProxyCreatorextends ProxyProcessorSupportimplements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAwareSmartInstantiationAwareBeanPostProcessor? - > BeanPostProcessor:后置處理器,在bean初始化完成前后做的事情
BeanFactoryAware:自動(dòng)裝配BeanFactory
2、AnnotationAwareAspectJAutoProxyCreator繼承體系深入研究
(1)關(guān)鍵方法分析
AbstractAutoProxyCreator.setBeanFactory?BeanFactoryAware的重寫方法
AbstractAutoProxyCreator.postProcessBeforeInstantiation 有后置處理器的邏輯
AbstractAdvisorAutoProxyCreator?重寫了setBeanFactory ,會(huì)調(diào)用initBeanFactory
AnnotationAwareAspectJAutoProxyCreator?會(huì)重寫 initBeanFactory
(2)創(chuàng)建和注冊(cè)AnnotationAwareAspectJAutoProxyCreator的過程
①?傳入配置類,創(chuàng)建ioc容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);②?注冊(cè)配置類,調(diào)用refresh()刷新容器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {this();register(annotatedClasses);refresh(); }③ 注冊(cè)bean的后置處理器來方便攔截bean的創(chuàng)建
@Override public void refresh() throws BeansException, IllegalStateException {……// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);…… } public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {// ① 先獲取ioc容器已經(jīng)定義了的需要?jiǎng)?chuàng)建對(duì)象的所有BeanPostProcessorString[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);// ② 給容器中加別的BeanPostProcessorint beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));// ③ 分離BeanPostProcessorList<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 (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);priorityOrderedPostProcessors.add(pp);if (pp instanceof MergedBeanDefinitionPostProcessor) {internalPostProcessors.add(pp);}}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}}// 優(yōu)先注冊(cè)實(shí)現(xiàn)了PriorityOrdered接口的BeanPostProcessorsortPostProcessors(priorityOrderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// 再給容器中注冊(cè)實(shí)現(xiàn)了Ordered接口的BeanPostProcessorList<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);}}sortPostProcessors(orderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, orderedPostProcessors);// 然后,注冊(cè)沒實(shí)現(xiàn)優(yōu)先級(jí)接口的BeanPostProcessorList<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);}}// 把BeanPostProcessor注冊(cè)到BeanFactory中:就是調(diào)用beanFactory.addBeanPostProcessor(postProcessor);registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);// Finally, re-register all internal BeanPostProcessors.sortPostProcessors(internalPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, internalPostProcessors);// Re-register post-processor for detecting inner beans as ApplicationListeners,// moving it to the end of the processor chain (for picking up proxies etc).beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }/** 上面注冊(cè)BeanPostProcessor,實(shí)際上就是創(chuàng)建BeanPostProcessor對(duì)象,保存在容器中。 創(chuàng)建internalAutoProxyCreator的BeanPostProcessor【AnnotationAwareAspectJAutoProxyCreator】(1)創(chuàng)建Bean的實(shí)例。(2)populateBean:給bean的各種屬性賦值(3)initializeBean:初始化bean。1)invokeAwareMethods():處理Aware接口的方法回調(diào)。2)applyBeanPostProcessorsBeforeInitialization():應(yīng)用后置處理器的postProcessorBeforeInitialization()3)invokeInitMethods():執(zhí)行初始化方法4)applyBeanPostProcessorsAfterInitialization():執(zhí)行后置處理器的postProcessorAfterInitialization()(4)BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)創(chuàng)建成功;容器中有了aspectJAdvisorsBuilder */④?完成beanFactory初始化工作,創(chuàng)建剩下的單實(shí)例bean
@Override public void refresh() throws BeansException, IllegalStateException {……// 完成beanFactory初始化工作,創(chuàng)建剩下的單實(shí)例bean。finishBeanFactoryInitialization(beanFactory);…… }(1)遍歷獲取容器中所有的Bean,依次創(chuàng)建對(duì)象getBean(beanName)。getBean(beanName) -> doGetBean() -> getSingleton() -> (2)創(chuàng)建bean1)先從緩存中獲取當(dāng)前bean,如果能獲取到,說明bean之前被創(chuàng)建過的,直接使用。否則獲取不到再創(chuàng)建。只要?jiǎng)?chuàng)建好的bean都會(huì)被緩存起來。2)createBean(); 創(chuàng)建bean,AnnotationAwareAspectJAutoProxyCreator會(huì)在任何bean創(chuàng)建之前先嘗試返回bean實(shí)例。① resolveBeforeInstantiation(beanName, mbdToUse);解析BeforeInstantiation希望后置處理器在此能返回一個(gè)代理對(duì)象,如果能返回代理對(duì)象就使用,如果不能就繼續(xù)調(diào)用doCreateBean()創(chuàng)建bean。② doCreateBean(beanName, mbdToUse, args);真正的去創(chuàng)建一個(gè)bean實(shí)例,和上面創(chuàng)建bean的流程是一樣的。⑤?創(chuàng)建bean時(shí),嘗試返回代理對(duì)象
其中,AbstractAutoProxyCreator是InstantiationAwareBeanPostProcessor的后置處理器,在這里就會(huì)創(chuàng)建一個(gè)代理對(duì)象。
而AnnotationAwareAspectJAutoProxyCreator繼承于AbstractAutoProxyCreator,AnnotationAwareAspectJAutoProxyCreator又是@EnableAspectJAutoProxy會(huì)注冊(cè)的bean。
區(qū)別于BeanPostProcessor:
?? ?BeanPostProcessor是在Bean對(duì)象創(chuàng)建完成初始化前后調(diào)用的。
?? ?InstantiationAwareBeanPostProcessor是在創(chuàng)建bean實(shí)例之前先嘗試用后置處理器返回對(duì)象。
后置處理器先嘗試返回對(duì)象,bean = applyBeanPostProcessorsBeforeInstantiation()
? ? 拿到所有后置處理器,如果是InstantiationAwareBeanPostProcessor,就執(zhí)行后置處理器的postProcessBeforeInstantiation
后置處理器先嘗試返回對(duì)象,bean = applyBeanPostProcessorsAfterInstantiation()
3、創(chuàng)建AOP代理
(1)AnnotationAwareAspectJAutoProxyCreator【InstantiationAwareBeanPostProcessor】的作用
1) 每一個(gè)bean創(chuàng)建之前,調(diào)用postProcessBeforeInstantiation()
? ? 關(guān)心MathCalculator和LogAspect的創(chuàng)建
? ? ①?判斷當(dāng)前bean是否在advisedBeans中(保存了所有需要增強(qiáng)的bean)
? ? ②?判斷當(dāng)前bean是否是基礎(chǔ)類型的(Advice、Pointcut、Advisor、AopInfrastructureBean),或者是否是切面(@Aspect)
? ? ③?判斷是否需要跳過。
?? ?? ? ① 獲取候選的增強(qiáng)器(切面里的通知方法)【List<Advisor> candidateAdvisors】
?? ?? ? ?? ?每一個(gè)封裝的通知方法的增強(qiáng)器是InstantiationModelAwarePointcutAdvisor;
?? ??? ?? ? 判斷每一個(gè)增強(qiáng)器是否是AspectJPointcutAdvisor類型的,返回true。
?? ?? ? ②?永遠(yuǎn)返回false。
2)創(chuàng)建對(duì)象,調(diào)用postProcessAfterInstantiation()
? ? return wrapIfNecessary(bean, beanName, cacheKey); //?包裝如果需要的情況下。
? ? ①?獲取當(dāng)前bean的所有增強(qiáng)器(通知方法),封裝成Object[] specificInterceptors
?? ?? ? ① 找到候選的所有的增強(qiáng)器(哪些通知方法是需要切入當(dāng)前方法的)。
?? ?? ? ②?獲取到能在當(dāng)前bean使用的增強(qiáng)器。
?? ?? ? ③?給增強(qiáng)器排序。
? ? ②?保存當(dāng)前bean在advisedBeans中。
? ? ③?如果當(dāng)前bean需要增強(qiáng),創(chuàng)建當(dāng)前bean的代理對(duì)象。
?? ?? ? ①?獲取所有增強(qiáng)器(通知方法)。
?? ?? ? ②?保存到proxyFactroy中。
?? ?? ? ③?創(chuàng)建代理對(duì)象,spring自動(dòng)決定,是創(chuàng)建jdk動(dòng)態(tài)代理還是cglib的動(dòng)態(tài)代理(JdkDynamicAopProxy、ObjenesisCglibAopProxy)。
? ? ④?給容器中返回當(dāng)前組件使用cglib增強(qiáng)了的代理對(duì)象。
? ? ⑤?以后容器中獲取到的就是組件的代理對(duì)象,執(zhí)行目標(biāo)方法的時(shí)候,代理對(duì)象就會(huì)執(zhí)行通知方法的流程。
(2)AbstractAutoProxyCreator的postProcessBeforeInstantiation方法
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {Object cacheKey = getCacheKey(beanClass, beanName);if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {if (this.advisedBeans.containsKey(cacheKey)) {return null;}if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return null;}}// Create proxy here if we have a custom TargetSource.// Suppresses unnecessary default instantiation of the target bean:// The TargetSource will handle target instances in a custom fashion.if (beanName != null) {TargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {this.targetSourcedBeans.add(beanName);Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}}return null; }(3)AbstractAutoProxyCreator.wrapIfNecessary()方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (beanName != null && this.targetSourcedBeans.contains(beanName)) {return bean;}if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean; }4、目標(biāo)對(duì)象的目標(biāo)方法執(zhí)行流程(攔截器鏈獲取)
容器中保存了組件的代理對(duì)象(cglib增強(qiáng)后的對(duì)象),這個(gè)對(duì)象里面保存了詳細(xì)信息(比如增強(qiáng)器、目標(biāo)對(duì)象等等 )。
1)CglibAopProxy.intercept();攔截目標(biāo)方法的執(zhí)行
2)根據(jù)ProxyFactory對(duì)象獲取將要執(zhí)行的目標(biāo)方法攔截器鏈
?? ?List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
? ? ①?創(chuàng)建List<Object> interceptorList來保存所有攔截器,長(zhǎng)度為5
?? ?? ? 一個(gè)默認(rèn)的ExposeInvocationInterceptor?和4個(gè)增強(qiáng)器。
? ? ②?遍歷所有的增強(qiáng)器,將其轉(zhuǎn)為interceptor:registry.getInterceptors(advisor);
?? ?③將增強(qiáng)器轉(zhuǎn)為 List<MethodInterceptor>
?? ?? ? 如果是MethodInterceptor,直接加入到集合中。
?? ?? ? 如果不是,使用AdvisorAdapter將增強(qiáng)器轉(zhuǎn)為MethodInterceptor。
?? ?? ? 返回MethodInterceptor數(shù)組。
3)如果沒有攔截器鏈,直接執(zhí)行目標(biāo)方法。
? ? 攔截器鏈(每一個(gè)通知方法又被包裝為方法的攔截器,利用MethodInterceptor機(jī)制)
4)如果有攔截器鏈,把需要執(zhí)行的目標(biāo)對(duì)象、目標(biāo)方法、攔截器鏈等所有信息傳入創(chuàng)建的CglibMethodInvocation對(duì)象并調(diào)用proceed()方法。
(1)CglibAopProxy.intercept();
@Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Class<?> targetClass = null;Object target = null;try {if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// May be null. Get as late as possible to minimize the time we// "own" the target, in case it comes from a pool...target = getTarget();if (target != null) {targetClass = target.getClass();}List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {// We can skip creating a MethodInvocation: just invoke the target directly.// Note that the final invoker must be an InvokerInterceptor, so we know// it does nothing but a reflective operation on the target, and no hot// swapping or fancy proxying.Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = methodProxy.invoke(target, argsToUse);}else {// We need to create a method invocation...retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null) {releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}} }(2)獲取攔截器鏈DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice()
@Override 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);Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);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(actualClass)) {MethodInterceptor[] interceptors = registry.getInterceptors(advisor);MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();if (MethodMatchers.matches(mm, method, actualClass, 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(actualClass)) {Interceptor[] interceptors = registry.getInterceptors(advisor);interceptorList.addAll(Arrays.asList(interceptors));}}else {Interceptor[] interceptors = registry.getInterceptors(advisor);interceptorList.addAll(Arrays.asList(interceptors));}}return interceptorList; }5、攔截器鏈的觸發(fā)過程
攔截器鏈:
執(zhí)行CglibMethodInvocation對(duì)象的proceed方法。
new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
1)如果沒有攔截器直接執(zhí)行目標(biāo)方法;或者攔截器的索引和攔截器數(shù)組-1大小一樣(指定到了最后一個(gè)攔截器)執(zhí)行目標(biāo)方法。
? ? currentInterceptorIndex記錄當(dāng)前攔截器的索引,從-1開始。
?? ?每次執(zhí)行proceed()索引都會(huì)自增一次。
?? ?dm.interceptor.invoke(this);?也就是調(diào)用了CglibMethodInvocation的proceed方法。
2)鏈?zhǔn)将@取每一個(gè)攔截器,攔截器執(zhí)行invoke方法,每一個(gè)攔截器它是等待下一個(gè)攔截器執(zhí)行完成返回以后再來執(zhí)行。
? ? 攔截器鏈的機(jī)制,保證通知方法與目標(biāo)方法的執(zhí)行順序。
?(1)CglibMethodInvocation的proceed方法
@Override public Object proceed() throws Throwable {// We start with an index of -1 and increment early.// 如果沒有攔截器鏈,就會(huì)直接執(zhí)行目標(biāo)方法 。if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {return invokeJoinpoint();}Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {return dm.interceptor.invoke(this);}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.return proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);} }?(2)AspectJAfterThrowingAdvice的invoke方法
@Override public Object invoke(MethodInvocation mi) throws Throwable {try {return mi.proceed();}catch (Throwable ex) {if (shouldInvokeOnThrowing(ex)) {invokeAdviceMethod(getJoinPointMatch(), null, ex);}throw ex;} }(3)AfterReturningAdviceInterceptor的invoke方法
@Override public Object invoke(MethodInvocation mi) throws Throwable {Object retVal = mi.proceed();this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());return retVal; }(4)AspectJAfterAdvice的invoke方法
@Override public Object invoke(MethodInvocation mi) throws Throwable {try {return mi.proceed();}finally {invokeAdviceMethod(getJoinPointMatch(), null, null);} }(5)MethodBeforeAdviceInterceptor的invoke方法
@Override public Object invoke(MethodInvocation mi) throws Throwable {this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );return mi.proceed(); }(6)ExposeInvocationInterceptor的invoke方法
@Override public Object invoke(MethodInvocation mi) throws Throwable {MethodInvocation oldInvocation = invocation.get();invocation.set(mi);try {return mi.proceed();}finally {invocation.set(oldInvocation);} }三、AOP總結(jié)
1.AOP小結(jié)
(1)@EnableAspectJAutoProxy開啟AOP功能。
(2)@EnableAspectJAutoProxy會(huì)給容器中注冊(cè)一個(gè)組件,AnnotationAwareAspectJAutoProxyCreator。
(3)AnnotationAwareAspectJAutoProxyCreator是一個(gè)后置處理器。
(4)容器的創(chuàng)建流程
? ? ①?registerBeanPostProcessors()注冊(cè)后置處理器,創(chuàng)建AnnotationAwareAspectJAutoProxyCreator對(duì)象。
? ? ② finishBeanFactoryInitialization()?初始化剩下的單實(shí)例bean。
?? ?? ? ①??創(chuàng)建業(yè)務(wù)邏輯組件和切面組件。
?? ?? ? ②?AnnotationAwareAspectJAutoProxyCreator攔截組件的創(chuàng)建過程
?? ?? ? ③?在組件創(chuàng)建完成之后,判斷組件是否需要增強(qiáng)。
?? ??? ?? ? 是:切面的通知方法,包裝成增強(qiáng)器(Advisor),給業(yè)務(wù)邏輯組件創(chuàng)建一個(gè)代理對(duì)象。
(5)執(zhí)行目標(biāo)方法(代理對(duì)象執(zhí)行目標(biāo)方法)
? ? ① CglibAopProxy.intercept();進(jìn)行攔截
?? ?? ? ①?得到目標(biāo)方法的攔截器鏈(增強(qiáng)器包裝成攔截器MethodInterceptor)
?? ?? ? ②?利用攔截器的鏈?zhǔn)綑C(jī)制,依次進(jìn)入每一個(gè)攔截器進(jìn)行執(zhí)行。
?? ?? ? ③?執(zhí)行順序:前置通知 ->?目標(biāo)方法 ->?后置通知 ->返回通知/異常通知
?? ??? ??? ?
? ??
總結(jié)
以上是生活随笔為你收集整理的spring系列-注解驱动原理及源码-AOP使用及源码解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java类加载器、双亲委派、沙箱安全机制
- 下一篇: spring系列-注解驱动原理及源码-s