Detailed explanation of SpringAOP's JoinPoint class and Proceedingjoinpoint class, and AOP surround notification to obtain annotation information

1. JoinPoint class, Proceedingjoinpoint class

1. When using springboot to write AOP, there is a JoinPoint class used to obtain information about the proxy class and the proxy class.

JointPoint is an identifiable point during program running. This point can be used as the AOP entry point. The JointPoint object contains a lot of information related to the cut. Such as entry point objects, methods, properties, etc. We can obtain the status and information of these points through reflection, which is used for tracing and recording logging application information.

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

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

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

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

2. Proceedingjoinpoint inherits JoinPoint. The proceed method is exposed based on JoinPoint.

Surround notification = pre + target method execution + post notification . The proceed method is used to start the execution of the target method. Exposing this method can support aspects such as aop:around.

( Proceedingjoinpoint only supports surround notification @Around, while other aspects only need to use JoinPoint. This is also the biggest difference between surround notification and pre- and post-notification methods. This is related to the aspect type )

Note:
joinpoint.getSignature(): Get information about the enhanced method.
After the object obtained by joinpoint.getSignature is forcibly converted into the implementation class MethodSignature, the getReturnType() method inside can be used to obtain the target method return value type.

@Before("customerJoinPointerExpression()")
public void beforeMethod(JoinPoint joinPoint){
    // 前置通知
	joinPoint.getSignature().getName(); // 获取目标方法名
	joinPoint.getSignature().getDeclaringType().getSimpleName(); // 获取目标方法所属类的简单类名
	joinPoint.getSignature().getDeclaringTypeName(); // 获取目标方法所属类的类名
	joinPoint.getSignature().getModifiers(); // 获取目标方法声明类型(public、private、protected)
	Object[] args = joinPoint.getArgs(); // 获取传入目标方法的参数,返回一个数组
	joinPoint.getTarget(); // 获取被代理的对象
	joinPoint.getThis(); // 获取代理对象自己
}
  // 匹配方法执行连接点方式
    @Around(value = "execution(* *..SomeserviceImpl.Dofirst(..))")
    public Object myAspectJ(ProceedingJoinPoint point) throws Throwable {
      
         //拦截的实体类
        Object target = point.getTarget();
        //拦截的方法名称
        String methodName = point.getSignature().getName();
        //拦截的方法参数
        Object[] args = point.getArgs();
        //拦截的放参数类型
        Class[] parameterTypes = ((MethodSignature)point.getSignature()).getMethod().getParameterTypes();

        object = point.proceed(); //目标方法的执行
        return null;
    }

2. AOP surround notification to obtain annotation information

1. Concept

Annotation is information written in the source code. It can provide additional information beyond the code. It has its own structure. You can use tools to extract this structured information.
Simply put, annotations are structured comments written above the program. Java will read the message according to its structure and perform corresponding operations.
For example, if the @Override annotation is marked on a method, during compilation, Java will check whether the current method overloads the method of the parent class, and if not, an error will be reported.

Java comes with standard annotations
@Override: indicates that the current method definition will override the method in the parent class;
@Deprecated: indicates that the code is deprecated, and the compiler will issue a warning if code annotated with @Deprecated is used;
@SuppressWarnings: indicates Turn off compiler warning messages.

Use the above annotations to generate your own annotations, just like defining a class yourself, you can create a custom annotation through @interface.

[@Target]     //限定注解可以标注的位置:ANNOTATION_TYPE、CONSTRUCTOR 、FIELD 、LOCAL_VARIABLE 、METHOD 、PACKAGE 、PARAMETER 、TYPE
[@Retention]  //说明了这个注解的存活时间	:SOURCE,CLASS ,RUNTIME
[@Documented] // 将注解中的元素包含到 Javadoc 中去	
[@Inherited]  //子类自动拥有父类的注解	
public @interface [名称] {
     // 元素
     String value() default "hello";
}

[@Retention]
RetentionPolicy.SOURCE: The annotation is only retained in the source code stage, and it will be discarded and ignored when the compiler compiles;
RetentionPolicy.CLASS: The annotation is only retained until compilation is in progress, and it will not be loaded into the JVM. ;
RetentionPolicy.RUNTIME: Annotations can be retained until the program is running, and they will be loaded into the JVM, so the annotations can be obtained when the program is running .

2. Code examples

annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AopCache 
{
    /**
     * 每个方法唯一的key
     */
    String key();
}

Section type:

@Aspect    //标注增强处理类(切面类)
@Component //交由Spring容器管理
@Order(0)  //设置优先级,值越低优先级越高
public class MyaspectJ {

    //定义增强,pointcut连接点使用@annotation(xxx)进行定义
    @Pointcut(value = "@annotation(xx.xx.xx.AopCache)")
    public void methodPointcut(){}

    // 匹配方法执行连接点方式
    @Around("methodPointcut()")
    public Object myAspectJ(ProceedingJoinPoint point) throws Throwable {
    
        // 获取方法上的注解
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        AopCache annotation = method.getAnnotation(AopCache.class);
        //获取key
        String key = annotation.key();

        object = point.proceed();   // 1. 目标方法的调用
        return null;
    }
}

If the method uses this annotation, it will directly perform aspect enhancement.

@AopCache(key = "自定义key值")
public String getAllType(){

   return "";
}

Guess you like

Origin blog.csdn.net/Little_Arya/article/details/129973814