现在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;
}
JoinPoint.StaticPart:提供访问连接点的静态部分,如被通知方法签名、连接点类型等:
public interface StaticPart {
Signature getSignature(); //返回当前连接点签名
String getKind(); //连接点类型
int getId(); //唯一标识
String toString(); //连接点所在位置的相关信息
String toShortString(); //连接点所在位置的简短相关信息
String toLongString(); //连接点所在位置的全部相关信息
}

环绕通知 ProceedingJoinPoint 执行proceed方法的作用是让目标方法执行,这也是环绕通知和前置、后置通知方法的一个最大区别。

Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。

  暴露出这个方法,就能支持 aop:around 这种切面(而其他的几种切面只需要用到JoinPoint,这跟切面类型有关), 能决定是否走代理链还是走自己拦截的其他逻辑。建议看一下 JdkDynamicAopProxy的invoke方法,了解一下代理链的执行原理。
典型的用法如下:
    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接口原始对象的更多相关文章

  1. java反射之获取所有方法及其注解(包括实现的接口上的注解),获取各种标识符备忘

    java反射之获取类或接口上的所有方法及其注解(包括实现的接口上的注解) /** * 获取类或接口上的所有方法及方法上的注解(包括方法实现上的注解以及接口上的注解),最完整的工具类,没有现成的工具类 ...

  2. Spring AOP高级——源码实现(3)AopProxy代理对象之JDK动态代理的创建过程

    spring-aop-4.3.7.RELEASE  在<Spring AOP高级——源码实现(1)动态代理技术>中介绍了两种动态代理技术,当然在Spring AOP中代理对象的生成也是运用 ...

  3. java中代理,静态代理,动态代理以及spring aop代理方式,实现原理统一汇总

    若代理类在程序运行前就已经存在,那么这种代理方式被成为 静态代理 ,这种情况下的代理类通常都是我们在Java代码中定义的. 通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生自相同的父类. ...

  4. 死磕Spring之AOP篇 - Spring AOP自动代理(三)创建代理对象

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...

  5. Spring核心框架 - AOP之动态代理机制

    动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码.动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类. ...

  6. 接口测试——HttpClient工具的https请求、代理设置、请求头设置、获取状态码和响应头

    目录 https请求 代理设置 请求头设置 获取状态码 接收响应头 https请求 https协议(Secure Hypertext Transfer Protocol) : 安全超文本传输协议, H ...

  7. AOP 技术原理——代理模式全面总结

    前言 非常重要的一个设计模式,也很常见,很多框架都有它的影子.定义就不多说了.两点: 1.为其它对象提供一个代理服务,间接控制对这个对象的访问,联想 Spring 事务机制,在合适的方法上加个 tra ...

  8. python 全栈开发,Day116(可迭代对象,type创建动态类,偏函数,面向对象的封装,获取外键数据,组合搜索,领域驱动设计(DDD))

    昨日内容回顾 1. 三个类 ChangeList,封装列表页面需要的所有数据. StarkConfig,生成URL和视图对应关系 + 默认配置 AdminSite,用于保存 数据库类 和 处理该类的对 ...

  9. 浅谈Spring的AOP实现-代理机制

    说起Spring的AOP(Aspect-Oriented Programming)面向切面编程大家都很熟悉(Spring不是这次博文的重点),但是我先提出几个问题,看看同学们是否了解,如果了解的话可以 ...

随机推荐

  1. char

    1 char是多少位的 2 java用的是什么方式表示字符 3 Unicode是用多少位表示的 1的答案是16位的,2的答案是Unicode,3的答案是16位 值得注意的是,2的答案并不是utf-8 ...

  2. 使用Eclipse+jlink调试STM32

    使用Eclipse+JLINK调试STM32 安装eclipse + CDT. 安装交叉编译工具(工具链ARM CROSS GCC--GUN ARM http://gnuarmeclipse.sour ...

  3. Google Adsense Google判断广告点击作弊的方式和数据 数据分析

    Google判断广告点击作弊的几种方式和数据 - 王庆东mas - 博客园 http://www.cnblogs.com/x-poior/p/5581327.html 作弊广告点击的CTR数据太高网上 ...

  4. Web开发(调试方法 F12)

    参考: 参考:MDN 调试HTML 参考:什么是浏览器开发者工具? 参考:检查和编辑页面与样式 工具参考:标记验证服务 工具参考:直接输入验证(直接输入HTML源码进行在线检查) 目录: 1.相关快捷 ...

  5. RMAN备份filesperset用法

    用filesperset控制备份集的尺寸 当指定filesperset参数时,rman比较filesperset与自动计算出来的值(对每个已分配通道的文件数目) 并取其中较小的那个值来保证所有的通道被 ...

  6. mysql 查询 最大值,最小值,第二大,第三大 一共四个值

    最大值:select max(num) from table 第二大值:select max(num) from tablewhere num not in(select max(num) from ...

  7. 如何优雅的运行起jmeter

    安装jdk 下载网站:http://www.oracle.com/,选个最新的版本就可以. 注意:11以后没有自动生成jre 配置环境变量 对于Java程序开发而言,主要会使用JDK的两个命令:jav ...

  8. hibernate连接数据库和使用

    hibernate.cfg.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibe ...

  9. asyncio之Coroutines,Tasks and Future

    asyncio之Coroutines,Tasks and Future Coroutines and Tasks属于High-level APIs,也就是高级层的api. 本节概述用于协程和任务的高级 ...

  10. 接口自动化测试持续集成--Soapui接口功能测试持续集成

    Soapui接口功能测试持续集成,需要先安装好maven和jenkins,maven和jenkins安装和系统环境配置比较简单,在这里不做叙述.   1.Soapui保存的工程文件 soapui工程保 ...