SpringAOP中的JointPoint和ProceedingJoinPoint使用详解

SpringAOP中的JointPoint和ProceedingJoinPoint使用详解

  • 概念
    • Joint Point
    • Pointcut
  • JointPoint和ProceedingJoinPoint区别
    • JointPoint
    • ProceedingJoinPoint
    • 两个接口的源码
    • JointPoint使用详解
      • 1 获取切入点所在目标对象
      • 2 获取连接点签名
      • 3. 获取方法上的注解
      • 4. 获取方法的参数

概念

Joint Point

JointPoint是程序运行过程中可识别的点,这个点可以用来作为AOP切入点。JointPoint对象则包含了和切入相关的很多信息。比如切入点的对象,方法,属性等。我们可以通过反射的方式获取这些点的状态和信息,用于追踪tracing和记录logging应用信息。

Pointcut

pointcut 是一种程序结构和规则,它用于选取join point并收集这些point的上下文信息。
pointcut通常包含了一系列的Joint Point,我们可以通过pointcut来同时操作jointpoint。单从概念上,可以把Pointcut当做jointpoint的集合。

JointPoint和ProceedingJoinPoint区别

JointPoint

通过JpointPoint对象可以获取到下面信息

# 返回目标对象,即被代理的对象
Object getTarget();

# 返回切入点的参数
Object[] getArgs();

# 返回切入点的Signature
Signature getSignature();

# 返回切入的类型,比如method-call,field-get等
 String getKind();

ProceedingJoinPoint

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

环绕通知=前置+目标方法执行+后置通知,proceed方法就是用于启动目标方法执行的

暴露出这个方法,就能支持 aop:around 这种切面(而其他的几种切面只需要用到JoinPoint,,这也是环绕通知和前置、后置通知方法的一个最大区别。这跟切面类型有关), 能决定是否走代理链还是走自己拦截的其他逻辑。建议看一下 JdkDynamicAopProxy的invoke方法,了解一下代理链的执行原理。

注:ProceedingJoinPoint is only supported for around advice

两个接口的源码

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
   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;  
 }

JointPoint使用详解

这里详细介绍JointPoint的方法,这部分很重要是coding核心参考部分。我们一般需要切点的哪些信息,可以有利于我们对该切点做逻辑处理?

1 切入点的方法名字及其参数
2 切入点方法标注的注解对象(通过该对象可以获取注解信息)
3 切入点目标对象(可以通过反射获取对象的类名,属性和方法名)

注:有一点非常重要,Spring的AOP只能支持到方法级别的切入。换句话说,切入点只能是某个方法

针对以上的需求JDK提供了如下API

1 获取切入点所在目标对象

Object targetObj =joinPoint.getTarget();

// 可以发挥反射的功能获取关于类的任何信息,例如获取类名如下
String className = joinPoint.getTarget().getClass().getName();

因为一个类有很多方法,为了获取具体切入点所在的方法可以通过如下API

2 获取连接点签名

getSignature());是获取到这样的信息 :修饰符+ 包名+组件名(类名) +方法名
这里我只需要方法名

String methodName = joinPoint.getSignature().getName()

这里应该用debug示意一下,后面补充======

3. 获取方法上的注解

方法1:xxxxxx是注解名字

  Signature signature = joinPoint.getSignature();
  MethodSignature methodSignature = (MethodSignature) signature;
  Method method = methodSignature.getMethod();

  if (method != null)
  {
      xxxxxx annoObj= method.getAnnotation(xxxxxx.class);
  }
  return null;

方法2:上面我们已经知道了方法名和类的对象,通过反射可以获取类的内部任何信息。

 		// 切面所在类
        Object target = joinPoint.getTarget();
 
        String methodName = joinPoint.getSignature().getName();
 
        Method method = null;
        for (Method m : target.getClass().getMethods()) {
            if (m.getName().equals(methodName)) {
                method = m;
               //  xxxxxx annoObj= method.getAnnotation(xxxxxx.class);同上
                break;
            }
        }

4. 获取方法的参数

这里返回的是切入点方法的参数列表

Object[] args = joinPoint.getArgs();

https://blog.csdn.net/kouryoushine/article/details/105299956

你可能感兴趣的:(JAVA,java,开发语言)