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. java基础(18):集合、Iterator迭代器、增强for循环、泛型

    1. 集合 1.1 集合介绍 集合,集合是java中提供的一种容器,可以用来存储多个数据. 在前面的学习中,我们知道数据多了,可以使用数组存放或者使用ArrayList集合进行存放数据.那么,集合和数 ...

  2. python网络爬虫进阶之HTTP原理,爬虫的基本原理,Cookies和代理介绍

    目录 一.HTTP基本原理 (一)URI和URL (二)超文本 (三)HTTP和HTTPS (四)HTTP请求过程 (五)请求 1.请求方法 2.请求的网址 3.请求头 4.请求体 (六)响应 1.响 ...

  3. Java的包

    Java 包 Java面向对象的核心的概念:类.接口.抽象类.对象:[主体] 包的定义: 指的是一个程序的目录,在最早的时候,如果要开发一个程序,只需要定义一个Java文件,而后在这个文件中编写所需要 ...

  4. Dynamics CRM中的注释(Note)及RollupRequest消息初探

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复161或者20151015可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 注释,这个实体的架构名称是Ann ...

  5. Android开发利器之pidcat

    介绍pidcat: pidcat 是Android届JakeWharton大神开发的一款命令行工具,堪称Android开发利器,它能方便Android程序猿捕获日志,过滤日志,定位程序问题,超级好用. ...

  6. Spring Cloud Netflix Ribbon详细介绍及自定义规则策略

    之前文章我们介绍了如何配置具有Ribbon轮询机制的负载均衡策略的消费者,这次来具体了解一下Ribbon的一些细节,以及如何自定义负载均衡策略等. 说一下Ribbon实现负载均衡的大致思路.它通过用@ ...

  7. BayaiM__SQLLDR_linux_shell高级版

    BayaiM__SQLLDR_linux_shell高级版   备注:1.因公司在职,商业机密,顾IP地方加了"*"号,你可以任意写一个数字做IP做就好.2.不要瞎BB,哥自己写的 ...

  8. [PHP] 新版本PHP7.4与新版本MySQL8认证问题

    mysql8的默认密码加密方式是caching_sha2_password,PHP7.4连接mysql的加密方式也为caching_sha2_password,这个地方要注意. 当为了兼容旧版的客户端 ...

  9. fiddler---Fiddler工具详细介绍

    在做测试的过程中,遇到一些问题都会去进行抓包,抓包可以帮助我们解决很多问题,抓包工具有很多比如fiddler,浏览器调试工具(F12),charles等,抓包工具是我们测试人员必不可少的一项技能. 什 ...

  10. C++ 基础语法 快速复习笔记---面对对象编程(2)

    1.C++面对对象编程: a.定义: 类定义是以关键字 class 开头,后跟类的名称.类的主体是包含在一对花括号中.类定义后必须跟着一个分号或一个声明列表. 关键字 public 确定了类成员的访问 ...