AOP之proceedingjoinpoint和joinpoint区别(获取各对象备忘)、动态代理机制及获取原理代理对象、获取Mybatis Mapper接口原始对象
现在AOP的场景越来越多,所以我们有必要理解下和AOP相关的一些概念和机制。基础知识和原理类大家搜索spring aop/aspectj,有大量现成的可以参考,基本上只要理解了jdk动态代理、cglib字节码动态生成代理就足够了,而且必须知道这个代理类是spring托管的(如果是自己创建的代理类,是无法被拦截的,此时只能使用过滤器/拦截器机制,他们本身是链式的,跟代理无关),所以这里就不重复废话了。
import org.aspectj.lang.reflect.SourceLocation;
public interface JoinPoint {
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
Object getThis(); //返回AOP代理对象,也就是com.sun.proxy.$Proxy18
Object getTarget(); //返回目标对象,一般我们都需要它或者(也就是定义方法的接口或类,为什么会是接口呢?这主要是在目标对象本身是动态代理的情况下,例如Mapper。所以返回的是定义方法的对象如aoptest.daoimpl.GoodDaoImpl或com.b.base.BaseMapper<T, E, PK>)
Object[] getArgs(); //返回被通知方法参数列表
Signature getSignature(); //返回当前连接点签名 其getName()方法返回方法的FQN,如void aoptest.dao.GoodDao.delete()或com.b.base.BaseMapper.insert(T)(需要注意的是,很多时候我们定义了子类继承父类的时候,我们希望拿到基于子类的FQN,这直接可拿不到,要依赖于AopUtils.getTargetClass(point.getTarget())获取原始代理对象,下面会详细讲解)
SourceLocation getSourceLocation();//返回连接点方法所在类文件中的位置
String getKind(); //连接点类型
StaticPart getStaticPart(); //返回连接点静态部分
} public interface ProceedingJoinPoint extends JoinPoint {
public Object proceed() throws Throwable;
public Object proceed(Object[] args) throws Throwable;
}
public interface StaticPart {
Signature getSignature(); //返回当前连接点签名
String getKind(); //连接点类型
int getId(); //唯一标识
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
}
环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。
Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。

public Object around(ProceedingJoinPoint point) throws Throwable {
Signature signature = point.getSignature();
// AopUtils.getTargetClass(point.getTarget())获取原始对象,例如对于Mapper而言,它获取的是具体代理的Mapper如com.b.mapper.DefaultDsMapper(如果前者继承了后者的话)而不是定义该方法的Mapper如com.b.base.BaseMapper<Info, InfoExample, InfoKey>,如下图
Type[] types = AopUtils.getTargetClass(point.getTarget()).getGenericInterfaces(); // getGenericInterfaces方法能够获取类/接口实现的所有接口
Annotation nologgingAnno = ((Class)types[0]).getAnnotation(Nologging.class); // type是所有类型的父接口
MethodSignature methodSignature = (MethodSignature)signature;
Method targetMethod = methodSignature.getMethod();
现在来补充下Java中Type接口与Class类的区别联系。
package java.lang.reflect; /**
* Type is the common superinterface for all types in the Java
* programming language. These include raw types, parameterized types,
* array types, type variables and primitive types.
*
* @since 1.5
*/
public interface Type {
/**
* Returns a string describing this type, including information
* about any type parameters.
*
* @implSpec The default implementation calls {@code toString}.
*
* @return a string describing this type
* @since 1.8
*/
default String getTypeName() {
return toString();
}
}
其主要的子类包括:
总结来说:
- Type是一个接口。
- Type是Java中所有类型的父接口,有一些子类,如上所示。
- Type包括:raw type(原始类型,对应Class),parameterized types(参数化类型), array types(数组类型), type variables(类型变量) and primitive types(基本类型,对应Class).
- Type是JDK1.5引入的,主要是为了泛型。
Type接口与Class类的区别联系
- Type是Class的父接口。
- Class是Type的子类。
提示:因为AOP是基于动态代理生成,如果想要仔细研究生成的代理类长什么样,可以设置系统参数-Dsun.misc.ProxyGenerator.saveGeneratedFiles=true,这样就会保存所有自动生成的代理类(注:生产环境严禁使用)。
参考:https://blog.csdn.net/cxh5060/article/details/45151863(拦截自定义注解,需要注意的是,标准的AOP表达式@annotation(com.xxx.yyy.annotation.CustomAnnotation)只能拦截实现类方法上的注解,无法拦截接口上的注解,如有需根据接口方法上的注解拦截的需求,需使用spring bean生命周期的BeanPostProcessor动态生成代理,而不是采用简单的AOP实现)
https://www.cnblogs.com/akaneblog/p/6720513.html(jdk动态代理手工编写,一般框架使用,比如spring aop、mybatis中logger也使用了动态代理)
https://www.cnblogs.com/haiq/p/4304615.html、https://blog.csdn.net/xlgen157387/article/details/82497594(cglib vs jdk动态代理性能参考)
https://blog.csdn.net/u010061691/article/details/50857798(进一步加了解释,实际上InvocationHandler是要被明确调用的,只不过在AOP中通常被框架调用了,如果是应用自己编写的话,则需要代码中通过InvocationHandler.getProxy,然后强转、再调用。https://dzone.com/articles/java-dynamic-proxies)
https://dzone.com/articles/cglib-missing-manual(cglib手册)
AOP之proceedingjoinpoint和joinpoint区别(获取各对象备忘)、动态代理机制及获取原理代理对象、获取Mybatis Mapper接口原始对象的更多相关文章
- java反射之获取所有方法及其注解(包括实现的接口上的注解),获取各种标识符备忘
java反射之获取类或接口上的所有方法及其注解(包括实现的接口上的注解) /** * 获取类或接口上的所有方法及方法上的注解(包括方法实现上的注解以及接口上的注解),最完整的工具类,没有现成的工具类 ...
- Spring AOP高级——源码实现(3)AopProxy代理对象之JDK动态代理的创建过程
spring-aop-4.3.7.RELEASE 在<Spring AOP高级——源码实现(1)动态代理技术>中介绍了两种动态代理技术,当然在Spring AOP中代理对象的生成也是运用 ...
- java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总
若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...
- 死磕Spring之AOP篇 - Spring AOP自动代理(三)创建代理对象
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...
- Spring核心框架 - AOP之动态代理机制
动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码.动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类. ...
- 接口测试——HttpClient工具的https请求、代理设置、请求头设置、获取状态码和响应头
目录 https请求 代理设置 请求头设置 获取状态码 接收响应头 https请求 https协议(Secure Hypertext Transfer Protocol) : 安全超文本传输协议, H ...
- AOP 技术原理——代理模式全面总结
前言 非常重要的一个设计模式,也很常见,很多框架都有它的影子.定义就不多说了.两点: 1.为其它对象提供一个代理服务,间接控制对这个对象的访问,联想 Spring 事务机制,在合适的方法上加个 tra ...
- python 全栈开发,Day116(可迭代对象,type创建动态类,偏函数,面向对象的封装,获取外键数据,组合搜索,领域驱动设计(DDD))
昨日内容回顾 1. 三个类 ChangeList,封装列表页面需要的所有数据. StarkConfig,生成URL和视图对应关系 + 默认配置 AdminSite,用于保存 数据库类 和 处理该类的对 ...
- 浅谈Spring的AOP实现-代理机制
说起Spring的AOP(Aspect-Oriented Programming)面向切面编程大家都很熟悉(Spring不是这次博文的重点),但是我先提出几个问题,看看同学们是否了解,如果了解的话可以 ...
随机推荐
- [daily] cscope
手册: http://cscope.sourceforge.net/cscope_vim_tutorial.html 下载 cscope_maps.vim 到 $HOME/.vim/plugin/ 目 ...
- 骑士(树形dp)
题意:给你一个基环树森林,每个点有一个权值,一条边上的两个节点不能同时选择.选取任意个节点,求最大权值和 对于每颗基环树:找环→断边→树形dp(没有上司的舞会) #include<iostrea ...
- check failed status == cudnn_status_success (4 vs. 0) cudnn_status_internal_error
Check failed: error == cudaSuccess (30 vs. 0) unknown error 这个有可能是显存不足造成的,或者网络参数不对造成的 check failed ...
- 007-chrome插件系列
1.Axure RP Extension for Chrome 2.Charset 3.CLEAN crxMouse Gestures 4.Google 翻译 5.JSONView 6.restlet
- T-SQL语言基础(1)之理论背景
从学校就开始接触和使用 SQL 了,但一直没有怎么细细去了解它,最近入职的公司比较重 T-SQL 部分,所以就准备系统的学习一下. 买了一本<Microsoft SQL Server 2008 ...
- box-sizing:border-boxing的使用
<div class="box"></div> .box { margin-top: 200px; margin-left: 200px; backgrou ...
- java iso8859 转utf8
http://www.it1352.com/110853.html https://blog.csdn.net/RR369_yyh/article/details/77582441 /* 输出 下面这 ...
- Mockito常用方法及示例
Mockit是一个开源mock框架,官网:http://mockito.org/,源码:https://github.com/mockito/mockito 要使用Mockit,首先需要在我们工程中引 ...
- MyEclipse破解步骤
1.下载安装(注:安装后不要打开myeclipse,以下步骤完成方可打开) 2.解压破解文件 3.打开文件夹patch 3.全部复制 4.找到myeclipse的安装目录,打开plugins文件夹 5 ...
- vue中上传文件之multipart/form-data
首先在项目里用了拦截器的,由于拦截器会将传递的参数转成对象,所以你i提交的时候会发现multipart/form-data或转变成application/json 其次关于input的文件上传是需要一 ...