学习笔记Spring中自定义注解

Posted 棉花糖灬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习笔记Spring中自定义注解相关的知识,希望对你有一定的参考价值。

本文参考了文章@data注解_基础篇:深入解析JAVA注解机制Spring项目中自定义注解的使用

简单来说Spring中的自定义注解是基于AOP(面向切面编程)来实现的,即在一个方法的执行前后对其做修改,以新增一些功能。所以在看本文之前需要先了解AOP的相关知识。

1. 自定义注解类

新建Maven工程,创建注解类MyAnno

package ele.me;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnno {
    // 注意是带小括号的
    String value() default "";
    int type() default 0;
}

上述代码中注解类上的三个注解称为自定义注解的元注解,自定义注解的元注解主要有以下五个:

  • @Documented:注解信息会被添加到Java文档中,不常用
  • @Retention:注解的生命周期,表示注解会被保留到什么阶段,其取值有3个:
    • SOURCE:注解将被编译器丢弃,生成的class不包含注解信息
    • CLASS:注解在class文件中可用,但会被JVM丢弃;当注解未定义Retention值时,默认值是CLASS
    • RUNTIME:注解信息在运行期保留,可以通过反射机制读取注解的信息
  • @Target:指定注解作用范围,可指定多个
    • TYPE:适用范围:类、接口、注解类型,枚举类型enum
    • FIELD:作用于类属性 (includes enum constants)
    • METHOD:作用于方法
    • PARAMETER:作用于参数声明
    • CONSTRUCTOR:作用于构造函数声明
    • LOCAL_VARIABLE:作用于局部变量声明
    • ;:作用于注解声明
    • PACKAGE:作用于包声明
    • TYPE_PARAMETER:作用于类型参数(泛型参数)声明
    • TYPE_USE:作用于使用类型的任意语句(不包括class)
  • @Inherited:表示当前注解会被注解类的子类继承。即在子类Class 通过getAnnotations()可获取父类被@Inherited修饰的注解
  • @Repetable:JDK1.8新加入的,表明自定义的注解可以在同一个位置重复使用

2. Controller方法应用注解

创建一个Controller,并将http请求映射到指定方法上

package ele.me;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyAnnoController {
    @MyAnno(value = "MyAnno的value", type = 1)
    @GetMapping("/myAnno/{id}")
    @ResponseBody
    public String myAnno(@PathVariable("id") Integer id) {
        System.out.println("Controller执行,传入id为:" + id);
        return "Success";
    }
}

当上述代码没有添加@MyAnno注解时,在浏览器访问localhost:8080/myAnno/5,控制台打印的内容为:Controller执行,传入id为:5,浏览器页面显示的内容为Success

3. AOP方法定义注解功能

下面添加上@MyAnno注解并指定其value和type属性的值,利用AOP实现注解的功能

package ele.me;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAnnoAOP {

    @Pointcut("@annotation(MyAnno)")
    private void pointcut(){}

    @Around("pointcut() && @annotation(myAnno)")
    public Object myAnnoAroundAdvice(ProceedingJoinPoint joinPoint, MyAnno myAnno) {
        // 获取注解传来的参数
        System.out.println("MyAnno.value: " + myAnno.value());
        System.out.println("MyAnno.type: " + myAnno.type());
        // 获取连接点的参数,即myAnno方法的id参数
        Object[] args = joinPoint.getArgs();
        // 将id的值变为原来的平方
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof Integer) {
                args[i] = (Integer)args[i] * (Integer)args[i];
            }
        }
        Object result = null;
        try {
            // 调用原来的myAnno方法进行处理
            result = joinPoint.proceed(args);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        // 对myAnno方法的返回结果进行修改
        if (result instanceof String) {
            result += " aroundAdvice";
        }
        return result;
    }
}

上面这段代码为@MyAnno注解添加了3个功能,一是打印添加注解时传来的value和type的属性值,我们可以根据传入参数值的不同进行不同的操作;二是将原来myAnno方法的入参id的值变为原来的平方;三是将原来myAnno方法的返回值加上字符串“ aroundAdvice”。

再在浏览器中访问相同的网页localhost:8080/myAnno/5,控制台打印的内容为:Controller执行,传入id为:25,浏览器页面显示的内容为Success aroundAdvice

以上是关于学习笔记Spring中自定义注解的主要内容,如果未能解决你的问题,请参考以下文章

spring中自定义注解

Java中自定义注解

Spring Bootspringboot中自定义配置项

Spring Bootspringboot中自定义配置项

Spring Bootspringboot中自定义配置项

spring学习笔记四:spring常用注解总结