Spring-AOP源码分析随手记(一)
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源码分析随手记(一)的更多相关文章
- spring AOP源码分析(三)
在上一篇文章 spring AOP源码分析(二)中,我们已经知道如何生成一个代理对象了,那么当代理对象调用代理方法时,增强行为也就是拦截器是如何发挥作用的呢?接下来我们将介绍JDK动态代理和cglib ...
- Spring AOP 源码分析 - 拦截器链的执行过程
1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...
- Spring AOP 源码分析 - 创建代理对象
1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...
- Spring AOP 源码分析 - 筛选合适的通知器
1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...
- Spring AOP 源码分析系列文章导读
1. 简介 前一段时间,我学习了 Spring IOC 容器方面的源码,并写了数篇文章对此进行讲解.在写完 Spring IOC 容器源码分析系列文章中的最后一篇后,没敢懈怠,趁热打铁,花了3天时间阅 ...
- Spring AOP源码分析(三):基于JDK动态代理和CGLIB创建代理对象的实现原理
AOP代理对象的创建 AOP相关的代理对象的创建主要在applyBeanPostProcessorsBeforeInstantiation方法实现: protected Object applyBea ...
- 5.2 Spring5源码--Spring AOP源码分析二
目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...
- 5.2 spring5源码--spring AOP源码分析二--切面的配置方式
目标: 1. 什么是AOP, 什么是AspectJ 2. 什么是Spring AOP 3. Spring AOP注解版实现原理 4. Spring AOP切面原理解析 一. 认识AOP及其使用 详见博 ...
- spring aop 源码分析(三) @Scope注解创建代理对象
一.源码环境的搭建: @Component @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON,proxyMode = ScopedP ...
- 最简 Spring AOP 源码分析!
前言 最近在研究 Spring 源码,Spring 最核心的功能就是 IOC 容器和 AOP.本文定位是以最简的方式,分析 Spring AOP 源码. 基本概念 上面的思维导图能够概括了 Sprin ...
随机推荐
- winform批量更新数据_长时间的执行会导致界面卡死
前言:使用winform触发一个事件后执行的代码,如果耗时非常长,则会导致窗口界面假死! 本人最近通过winform窗体执行一项:需要批量更新一批数据库的数据的操作的任务时,由于数据量达到百万级别, ...
- HTML颜色名称大全
所有浏览器支持的颜色名称,所有现代浏览器都支持以下140种颜色名称(单击颜色名称或十六进制值,以将颜色视为背景颜色以及不同的文本颜色): 有关HTML颜色的完整概述,请访问我们的颜色教程. 颜色名称 ...
- 往element 模块里面渲染数据
<template> <div class="hello"> <section class="el-container"> ...
- css媒体查询aspect-ratio宽高比在less中的使用
css媒体查询有一个 宽高比很方便,aspect-ratio ,可以直接使用宽/高 来进行页面适配 使用样例如下: // 宽高比在((320/50)+(728/90))/2 两个尺寸中间值以内 适 ...
- 【XML】XPath表达式
XPath简介 XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言. XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力.起 ...
- C# 第三方库
基本上选用的都是 https://www.nuget.org 分类中最流行的那个库 1. 日志工具库 NLOG Stackify.com 简单入门文章 https://stackify.com/nl ...
- OSI模型级各层功能
OSI(Open System Interconnection 即 开放系统互联)国际标准化组织(ISO)制定了OSI模型,该模型定义了不同计算机互联的标准,是设计和描述计算机网络通信的基本框架.OS ...
- [PHP] PDO对象与mysql的连接超时
在php中每一个new的PDO对象,都会去连接mysql,都会创建一条tcp连接.当pdo对象赋予的变量是一个的时候,那么他只会保持一个tcp连接,没有被引用的对象连接会直接断掉.如果不对这个对象进行 ...
- 面向过程编程&面向对象编程
面向过程编程 Procedure Oriented Programming C语言是面向过程编程的,面向过程编程主要使用顺序.条件选择.循环三种基本结构来编写程序. 顺序:按照时间轴顺序完成每个处理: ...
- 初学Python几个小程序练习
使用格式化输出的三种方式实现以下输出(name换成自己的名字,既得修改身高体重,不要厚颜无耻) name = 'ABDMLBM' height = 175 weight = 140 # "M ...