Java 自定义注解

Java 自定义注解, 以及@interface @Target @Retention @Around @Before @After ProceedingJoinPoint JoinPoint 等用法

注解应用非常广泛,我们自定义注解能简化开发各种各种业务

一、关键字解释

(1) 定义注解时,关键字

@interface 来表示注解类的类型

@Target @Retention 这两个具体值,需要分析注解的应用场景来确定;

对于"调用方法时打印入参和出参"的例子,是在调用调用方法时,则使用RetentionPolicy.RUNTIME, 且作用于方法上,则使用ElementType.METHOD;

(2) 实现注解时,关键字

@Before、@After、@AfterReturning 方法的入参是JoinPoint类型

@Around 方法的入参是ProceedingJoinPoint类型

ProceedingJoinPoint继承了JoinPoint类型,并扩展出了proceed()方法,执行proceed()也就是执行原始的函数具体业务方法,可以通过JoinPoint对象获取一些请求上的参数,比如request,parms等;

执行顺序:

@Around >> @Before >> 被添加注解的方法业务执行 >> @After >> @AfterReturning

特别注意:

注解中,可以存在@Around、@Before 、@After或、@AfterReturning任意组合

注解中,存在@Around ,也存在@Before 、@After或、@AfterReturning时、会先执行@Around;

在@Around中,执行参数的ProceedingJoinPoint.proceed(), 会触发@Before 、"被添加注解的方法业务执行" 、@After、@AfterReturning的执行,

在@Around中,不执行参数的ProceedingJoinPoint.proceed(), 不会触发@Before 、"被添加注解的方法业务执行",特别注意;所以正常逻辑中,ProceedingJoinPoint.proceed()都应该触发执行。

@Around 的返回值应该为 "被添加注解的方法业务执行" 的返回值。通过获取Object bizData = ProceedingJoinPoint.proceed(), 也可以对返回值加工再返回;

三、代码实现

(1) 定义注解

java 复制代码
package com.xxxxx.annotation;

import java.lang.annotation.*;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MethodParam {

    /**
     * 自定义方法, 日志描述信息, 可有可无
     *
     * @return
     */
    String description() default "";

    /**
     * 自定义方法1, 日志描述信息, 可有可无
     *
     * @return
     */
    String description1() default "";

    /**
     * 自定义方法2, 日志描述信息, 可有可无
     *
     * @return
     */
    String description2() default "";
}

其中description() description1() description2() 都是自定义方法(相当于调用注解时的传参),当业务需要就声明,不需要就无需声明

(2) 实现注解

java 复制代码
package com.xxxxx.annotation.annotationAspect;

import com.xxxxx.annotation.MethodParam;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class MethodParamAspect {

    /**
     * 声明切点
     */
    @Pointcut(value = "@annotation(com.xxxxx.annotation.MethodParam)")
    public void doPointCut() {
        System.out.print("执行doPointCut \n");
    }

    /**
     * 调用方法前后执行
     * @param joinPoint
     */
    @Around(value = "doPointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.print("执行doAround \n");

        //获取注解入参
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        MethodParam methodParamNew = method.getAnnotation(MethodParam.class);
        String description = methodParamNew.description();
        String description1 = methodParamNew.description1();
        String description2 = methodParamNew.description2();


        //被添加注解的方法业务执行
        Object bizData = joinPoint.proceed();

        //处理其他业务
        
        return bizData;
    }

    /**
     * 调用方法之【前】执行
     * @param joinPoint
     */
    @Before(value = "doPointCut()")
    public void doBefore(JoinPoint joinPoint){
        System.out.print("执行doBefore \n");
        //处理其他业务
    }


    /***
     * 调用方法之【后】执行
     *
     * @param joinPoint
     */
    @After(value = "doPointCut()")
    public void doAfter(JoinPoint joinPoint){
        System.out.print("执行doAfter \n");
        //处理其他业务
    }


    /***
     * @After执行之【后】执行
     *
     * @param joinPoint
     * @param res 具体业务的返回值 (可有可无)
     */
    @AfterReturning(value = "doPointCut()",returning = "res")
    public void doAfterReturning(JoinPoint joinPoint, String res){
        System.out.print("执行doAfterReturning \n");
        //处理其他业务
    }
}

(3) 使用注解

java 复制代码
package com.xxxxx.component;

import com.xxxxx.annotation.MethodParam;
import org.springframework.stereotype.Component;
import java.util.Random;

@Component
public class OrderComponent {

    @MethodParam(description = "aaa", description1 = "bbb", description2 = "ccc")
    public String testAnnotation(String val1, String val2){
        String aa = val1.concat(val2)
        .concat(String.valueOf(String.format("%04d",new Random().nextInt(9999))));
        System.out.print(aa + "\n");
        return aa;
    }
}
相关推荐
佚先森1 分钟前
2024ARM网络验证 支持一键云注入引流弹窗注册机 一键脱壳APP加固搭建程序源码及教程
java·html
大白要努力!2 分钟前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
菜鸟学Python3 分钟前
Python 数据分析核心库大全!
开发语言·python·数据挖掘·数据分析
一个小坑货10 分钟前
Cargo Rust 的包管理器
开发语言·后端·rust
bluebonnet2714 分钟前
【Rust练习】22.HashMap
开发语言·后端·rust
古月居GYH15 分钟前
在C++上实现反射用法
java·开发语言·c++
在下不上天40 分钟前
Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复
大数据·开发语言·python
tatasix1 小时前
MySQL UPDATE语句执行链路解析
数据库·mysql