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方法,打开,创建了个advisorRetrievalHelper切面工具,又是O重写 创建了aspectJAdvisorsBuilder

6.pic1图里明显看出有两个关键性方法:

postProcessBeforeInstantiation和postProcessAfterInitialization

显然是前后处理逻辑了。肯定先看前逻辑postProcessBeforeInstantiation啊

7.postProcessBeforeInstantiation

断点走起,居然是从这里进去的

所以这个之前分析IOC的createBean里的resolveBeforeInstantiation是AOP实现的关键。

8.分析postProcessBeforeInstantiation细节

8.1 isInfrastructureClass判断是否基础Bean

就是那种AOP本身的比如Advice、Pointcut、AopInfrastructureBean等,基础的这种直接返回不需要代理

8.2 shouldSkip是否要跳过(包含找出切面)

8.2.1找出增强器(那种切面里的@After、@Before的方法)

跟随断点跳跃到之前setBeanFactory创建的advisorRetrievalHelper里去了帮忙实现的找增强器

实际上这里面又分两部分了,一个是找事务的(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判断注解类型 创建不同类型Advice 放进缓存

最终由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()找到了我写的所有切面的增强方法

最终把整个切面类放到了advisorsCache的ConcurrentHashMap,以切面类的beanname作为key,增强器方法advice集合作为value

9.postProcessAfterInitialization

条件断点,当beanname = "calculate"时停住。找出增强器后,看看后续aop是怎么和目标类结合的。

10.postProcessAfterInitialization细节

断点已达。老办法,看看是从哪调来的:

原来是这里,ioc创建完对象并给属性赋完值之后。

回到postProcessAfterInitialization本身,就调了个wrapIfNecessary。逻辑都在里面了

10.1 找对应的增强器

打开断点继续,先主要是个getAdvicesAndAdvisorsForBean然后调findEligibleAdvisors然后就是以前跑过的找事务略。然后主要是findAdvisorsThatCanApply(名字也看得出,它能用的 这个bean对应的切面),进去又是个canApply(candidate, clazz, hasIntroductions),这就是具体判断了:

获取所有方法,用匹配器match去匹配是否匹配上了

循环记下,全部找出来,找增强器就结束了!

10.2 织入生成代理对象

回到wrapIfNecessary开始创建代理对象了:

这里面框起来是涉及注解配置的,对应你配置的:

@EnableAspectJAutoProxy(exposeProxy = true)

@EnableAspectJAutoProxy(proxyTargetClass = true)

如果这两个设置了的话,就会处理实现。

第二个是启动优先cglib,第一个是把代理对象创建好之后暴露出去,这样就能让原本this.dadd去调用方法本来不能增强的情况 可以用

((Calculate) AopContext.currentProxy()).add(numA,numB);也触发增强效果

后面的话就是创建个代理工厂ProxyFactory,把增强器设置进去,最后调用getProxy

一路跳转:

这就是最后网上背背背的东西了。在没有接口和没打优先cglib的话用jdk创建否则cglib创建。

问题:

1.怎么得出来继承结构哪些是重要的、哪些是不需要看不重要的

2.怎么整理出来的?

Spring-AOP源码分析随手记(一)的更多相关文章

  1. spring AOP源码分析(三)

    在上一篇文章 spring AOP源码分析(二)中,我们已经知道如何生成一个代理对象了,那么当代理对象调用代理方法时,增强行为也就是拦截器是如何发挥作用的呢?接下来我们将介绍JDK动态代理和cglib ...

  2. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  3. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  4. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  5. Spring AOP 源码分析系列文章导读

    1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...

  6. Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理

    AOP代理对象的创建 AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现: protected Object applyBea ...

  7. 5.2 Spring5源码--Spring AOP源码分析二

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  8. 5.2 spring5源码--spring AOP源码分析二--切面的配置方式

    目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...

  9. spring aop 源码分析(三) @Scope注解创建代理对象

    一.源码环境的搭建: @Component @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON,proxyMode = ScopedP ...

  10. 最简 Spring AOP 源码分析!

    前言 最近在研究 Spring 源码,Spring 最核心的功能就是 IOC 容器和 AOP.本文定位是以最简的方式,分析 Spring AOP 源码. 基本概念 上面的思维导图能够概括了 Sprin ...

随机推荐

  1. winform批量更新数据_长时间的执行会导致界面卡死

    前言:使用winform触发一个事件后执行的代码,如果耗时非常长,则会导致窗口界面假死!  本人最近通过winform窗体执行一项:需要批量更新一批数据库的数据的操作的任务时,由于数据量达到百万级别, ...

  2. HTML颜色名称大全

    所有浏览器支持的颜色名称,所有现代浏览器都支持以下140种颜色名称(单击颜色名称或十六进制值,以将颜色视为背景颜色以及不同的文本颜色): 有关HTML颜色的完整概述,请访问我们的颜色教程. 颜色名称 ...

  3. 往element 模块里面渲染数据

    <template> <div class="hello"> <section class="el-container"> ...

  4. css媒体查询aspect-ratio宽高比在less中的使用

    css媒体查询有一个 宽高比很方便,aspect-ratio ,可以直接使用宽/高 来进行页面适配   使用样例如下: // 宽高比在((320/50)+(728/90))/2 两个尺寸中间值以内 适 ...

  5. 【XML】XPath表达式

    XPath简介 XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言. XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力.起 ...

  6. C# 第三方库

    基本上选用的都是 https://www.nuget.org 分类中最流行的那个库 1. 日志工具库 NLOG Stackify.com 简单入门文章  https://stackify.com/nl ...

  7. OSI模型级各层功能

    OSI(Open System Interconnection 即 开放系统互联)国际标准化组织(ISO)制定了OSI模型,该模型定义了不同计算机互联的标准,是设计和描述计算机网络通信的基本框架.OS ...

  8. [PHP] PDO对象与mysql的连接超时

    在php中每一个new的PDO对象,都会去连接mysql,都会创建一条tcp连接.当pdo对象赋予的变量是一个的时候,那么他只会保持一个tcp连接,没有被引用的对象连接会直接断掉.如果不对这个对象进行 ...

  9. 面向过程编程&面向对象编程

    面向过程编程 Procedure Oriented Programming C语言是面向过程编程的,面向过程编程主要使用顺序.条件选择.循环三种基本结构来编写程序. 顺序:按照时间轴顺序完成每个处理: ...

  10. 初学Python几个小程序练习

    使用格式化输出的三种方式实现以下输出(name换成自己的名字,既得修改身高体重,不要厚颜无耻) name = 'ABDMLBM' height = 175 weight = 140 # "M ...