• SpringBoot:自定义注解


    目录

    一、注释简介

     二、自定义注解

    MyAnnotation注解

     获取注释内标记类的内容

     获取注释内标记属性的内容

     获取注释内标记方法的内容

      获取注释内标记参数的内容

     三、自定义注解日志的使用

    一、注释简介

    Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。 注解相关类都包含在java.lang.annotation包中。

     Java注解分类

            JDK基本注解
            JDK元注解
            自定义注解

     JDK基本注解

    @Override
    重写

    @SuppressWarnings(value = "unchecked")
    压制编辑器警告

     JDK元注解

    @Retention:定义注解的保留策略
    @Retention(RetentionPolicy.SOURCE)             //注解仅存在于源码中,在class字节码文件中不包含
    @Retention(RetentionPolicy.CLASS)              //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,
    @Retention(RetentionPolicy.RUNTIME)            //注解会在class字节码文件中存在,在运行时可以通过反射获取到

    @Target:指定被修饰的Annotation可以放置的位置(被修饰的目标)
    @Target(ElementType.TYPE)                      //接口、类
    @Target(ElementType.FIELD)                     //属性
    @Target(ElementType.METHOD)                    //方法
    @Target(ElementType.PARAMETER)                 //方法参数
    @Target(ElementType.CONSTRUCTOR)               //构造函数
    @Target(ElementType.LOCAL_VARIABLE)            //局部变量
    @Target(ElementType.ANNOTATION_TYPE)           //注解
    @Target(ElementType.PACKAGE)                   //包
    注:可以指定多个位置,例如:
    @Target({ElementType.METHOD, ElementType.TYPE}),也就是此注解可以在方法和类上面使用

    @Inherited:指定被修饰的Annotation将具有继承性

    @Documented:指定被修饰的该Annotation可以被javadoc工具提取成文档.

     自定义注解

    注解分类(根据Annotation是否包含成员变量,可以把Annotation分为两类):

    标记Annotation:
    没有成员变量的Annotation; 这种Annotation仅利用自身的存在与否来提供信息

    元数据Annotation:
    包含成员变量的Annotation; 它们可以接受(和提供)更多的元数据;

     如何自定义注解?

    使用@interface关键字, 其定义过程与定义接口非常类似, 需要注意的是:
       Annotation的成员变量在Annotation定义中是以无参的方法形式来声明的, 其方法名和返回值类型定义了该成员变量的名字和类型,
       而且我们还可以使用default关键字为这个成员变量设定默认值;

     二、自定义注解

    MyAnnotation注解

    1. package com.cdl.ssm.annotation;
    2. import java.lang.annotation.ElementType;
    3. import java.lang.annotation.Retention;
    4. import java.lang.annotation.RetentionPolicy;
    5. import java.lang.annotation.Target;
    6. /**
    7. * @author cdl
    8. * @site www.cdl.com
    9. * @create 2022-10-27 11:21
    10. *
    11. * MyAnnotation注解可以用在类、接口、属性、方法上
    12. * 注解运行期也保留
    13. * 不可继承
    14. */
    15. @Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
    16. @Retention(RetentionPolicy.SOURCE)
    17. public @interface MyAnnotation {
    18. String name();//注解中的属性
    19. }
    StudentController
    1. package com.cdl.ssm.annotation;
    2. /**
    3. * @author cdl
    4. * @site www.cdl.com
    5. * @create 2022-10-27 11:27
    6. */
    7. @MyAnnotation(name = "注解中的属性标记在类上")
    8. public class StudentController {
    9. @MyAnnotation(name="注解中的属性标记在属性上")
    10. private int age;
    11. @MyAnnotation(name="注解中的属性标记在方法上")
    12. public void edit(){
    13. }
    14. }

     

     

     获取注释内标记类的内容

    MyAnnotation 

    1. package com.cdl.ssm.annotation;
    2. import java.lang.annotation.ElementType;
    3. import java.lang.annotation.Retention;
    4. import java.lang.annotation.RetentionPolicy;
    5. import java.lang.annotation.Target;
    6. /**
    7. * @author cdl
    8. * @site www.cdl.com
    9. * @create 2022-10-27 11:21
    10. *
    11. * MyAnnotation注解可以用在类、接口、属性、方法上
    12. * 注解运行期也保留
    13. * 不可继承
    14. */
    15. @Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
    16. @Retention(RetentionPolicy.SOURCE)
    17. public @interface MyAnnotation {
    18. public String value() default "value修饰类、方法、属性";
    19. public String des() default "desc修饰类、方法、属性";//注解中的属性
    20. }

     MyAnnotation2 

    1. package com.cdl.ssm.annotation;
    2. import java.lang.annotation.ElementType;
    3. import java.lang.annotation.Retention;
    4. import java.lang.annotation.RetentionPolicy;
    5. import java.lang.annotation.Target;
    6. /**
    7. * @author cdl
    8. * @site www.cdl.com
    9. * @create 2022-10-27 11:21
    10. *
    11. * MyAnnotation注解可以用在类、接口、属性、方法上
    12. * 注解运行期也保留
    13. * 不可继承
    14. */
    15. @Target({ElementType.PARAMETER})
    16. @Retention(RetentionPolicy.SOURCE)
    17. public @interface MyAnnotation2 {
    18. public String value() default "value修饰类、方法、属性";
    19. public String des() default "desc修饰类、方法、属性";//注解中的属性
    20. }

     StudentController 

    1. package com.cdl.ssm.annotation;
    2. /**
    3. * @author cdl
    4. * @site www.cdl.com
    5. * @create 2022-10-27 11:27
    6. */
    7. @MyAnnotation(value = "注解中的属性标记在类上")
    8. public class StudentController {
    9. @MyAnnotation(value="注解中的属性标记在属性上")
    10. private int age;
    11. @MyAnnotation(value="注解中的属性标记在方法上")
    12. public void test1(@MyAnnotation2("用来修饰id参数")String id,@MyAnnotation2("用来修饰name参数")String name){
    13. }
    14. }

     Demo1 

    获取类上的内容

    1. package com.cdl.ssm.annotation.demo;
    2. import com.cdl.ssm.annotation.MyAnnotation;
    3. import com.cdl.ssm.annotation.StudentController;
    4. /**
    5. * @author cdl
    6. * @site www.cdl.com
    7. * @create 2022-10-27 11:43
    8. *
    9. * 目标:
    10. * 1.拿到类自定义注释的内容
    11. * 2.拿到方法自定义注释的内容
    12. * 3.拿到属性自定义注释的内容
    13. */
    14. public class Demo1 {
    15. public static void main(String[] args) {
    16. //获取到注释类
    17. MyAnnotation myAnnotation = StudentController.class.getAnnotation(MyAnnotation.class);
    18. System.out.println(myAnnotation.value());
    19. System.out.println(myAnnotation.des());
    20. }
    21. }

    结果:

     修改注解的代码 表示只有在运行时才能够拿到类中的注解

    1. @Target({ElementType.TYPE, ElementType.FIELD,ElementType.METHOD})
    2. @Retention(RetentionPolicy.RUNTIME)

    效果:

     获取注释内标记属性的内容

    StudentController 

    1. package com.cdl.ssm.annotation;
    2. /**
    3. * @author cdl
    4. * @site www.cdl.com
    5. * @create 2022-10-27 11:27
    6. */
    7. @MyAnnotation(value = "注解中的属性标记在类上")
    8. public class StudentController {
    9. @MyAnnotation(value="注解中的属性id标记在属性上")
    10. private String id;
    11. @MyAnnotation(value="注解中的属性name标记在属性上")
    12. private String name;
    13. @MyAnnotation(value="注解中的属性标记在方法上")
    14. public void test1(@MyAnnotation2("用来修饰id参数")String id,@MyAnnotation2("用来修饰name参数")String name){
    15. }
    16. }

     Demo1 

    1. package com.cdl.ssm.annotation.demo;
    2. import com.cdl.ssm.annotation.MyAnnotation;
    3. import com.cdl.ssm.annotation.StudentController;
    4. import java.lang.reflect.Field;
    5. /**
    6. * @author cdl
    7. * @site www.cdl.com
    8. * @create 2022-10-27 11:43
    9. *
    10. * 目标:
    11. * 1.拿到类自定义注释的内容
    12. * 2.拿到方法自定义注释的内容
    13. * 3.拿到属性自定义注释的内容
    14. */
    15. public class Demo1 {
    16. public static void main(String[] args) throws Exception{
    17. //获取到注释类
    18. MyAnnotation myAnnotation = StudentController.class.getAnnotation(MyAnnotation.class);
    19. // System.out.println(myAnnotation.value());
    20. // System.out.println(myAnnotation.des());
    21. //获取属性上的
    22. Field id = StudentController.class.getDeclaredField("id");
    23. Field name = StudentController.class.getDeclaredField("name");
    24. System.out.println(id.getAnnotation(MyAnnotation.class).value());
    25. System.out.println(name.getAnnotation(MyAnnotation.class).value());
    26. //使用场景
    27. // // MyAnnotation2 annotation2 = id.getAnnotation(MyAnnotation2.class);
    28. // Field[] declaredFields = StudentController.class.getDeclaredFields();
    29. // for (Field f : declaredFields) {
    30. // Annotation annotation1 = f.getAnnotation(myAnnotation.getClass());
    31. // if(annotation1 !=null){
    32. //
    33. // }
    34. // }
    35. }
    36. }

    效果:

     获取注释内标记方法的内容

    Demo1
    1. //获取方法上的
    2. Method m1 = StudentController.class.getDeclaredMethod("test1", String.class, String.class);
    3. System.out.println(m1.getAnnotation(MyAnnotation.class).value());

      获取注释内标记参数的内容

    Demo1

    1. //获取方法上的
    2. Method m1 = StudentController.class.getDeclaredMethod("test1", String.class, String.class);
    3. // System.out.println(m1.getAnnotation(MyAnnotation.class).value());
    4. //获取参数上的
    5. for (Parameter p : m1.getParameters()) {
    6. System.out.println(p.getAnnotation(MyAnnotation2.class).value());
    7. }

     三、自定义注解日志的使用

    MyLog 

    1. package com.cdl.ssm.annotation.aop;
    2. import java.lang.annotation.ElementType;
    3. import java.lang.annotation.Retention;
    4. import java.lang.annotation.RetentionPolicy;
    5. import java.lang.annotation.Target;
    6. /**
    7. * @author cdl
    8. * @site www.cdl.com
    9. * @create 2022-10-27 15:47
    10. */
    11. @Target(ElementType.METHOD)
    12. @Retention(RetentionPolicy.RUNTIME)
    13. public @interface MyLog {
    14. String desc();
    15. }

     MyLogAspect 

    1. package com.cdl.ssm.annotation.aop;
    2. import org.aspectj.lang.JoinPoint;
    3. import org.aspectj.lang.annotation.Before;
    4. import org.aspectj.lang.annotation.Pointcut;
    5. import org.aspectj.lang.reflect.MethodSignature;
    6. import org.slf4j.Logger;
    7. import org.slf4j.LoggerFactory;
    8. /**
    9. * @author cdl
    10. * @site www.cdl.com
    11. * @create 2022-10-27 15:50
    12. */
    13. public class MyLogAspect {
    14. private static final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);
    15. /**
    16. * 只要用到了com.javaxl.p2.annotation.springAop.MyLog这个注解的,就是目标类
    17. */
    18. @Pointcut("@annotation(com.cdl.ssm.annotation.aop.MyLog)")
    19. private void MyValid() {
    20. }
    21. @Before("MyValid()")
    22. public void before(JoinPoint joinPoint) {
    23. //joinPoint 可以拿到目标对象 目标方法 传递参数
    24. MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    25. logger.debug("[" + signature.getName() + " : start.....]");
    26. System.out.println("[" + signature.getName() + " : start.....]");
    27. MyLog myLog = signature.getMethod().getAnnotation(MyLog.class);
    28. logger.debug("【目标对象方法被调用时候产生的日志,记录到日志表中】:"+myLog.desc());
    29. System.out.println("【目标对象方法被调用时候产生的日志,记录到日志表中】:" + myLog.desc());
    30. }
    31. }

     DemoController 

    1. package com.cdl.ssm.annotation.aop;
    2. import org.springframework.stereotype.Controller;
    3. /**
    4. * @author cdl
    5. * @site www.cdl.com
    6. * @create 2022-10-27 15:48
    7. */
    8. @Controller
    9. public class DemoController {
    10. @MyLog(desc="这是一个测试类的方法")
    11. public void test(){
    12. System.out.println("测试方法");
    13. }
    14. }

     AnnotationTest 

    1. package com.cdl.shiro;
    2. import com.cdl.ssm.annotation.aop.DemoController;
    3. import org.junit.Test;
    4. import org.junit.runner.RunWith;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.test.context.ContextConfiguration;
    7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    8. /**
    9. * @author cdl
    10. * @site www.cdl.com
    11. * @create 2022-10-26 19:34
    12. */
    13. @RunWith(SpringJUnit4ClassRunner.class)
    14. @ContextConfiguration(locations={"classpath:applicationContext.xml"})
    15. public class AnnotationTest {
    16. @Autowired
    17. private DemoController demoController;
    18. @Test
    19. public void test(){
    20. demoController.test();
    21. }
    22. }

    若在AnnotationTest 和MyLogAspect 中各打一个断点 则会先进入MyLogAspect,其中有前置通知

  • 相关阅读:
    JAVA设计模式3:抽象工厂模式,这是一种创建型设计模式
    一篇打通,pytest自动化测试框架详细,从0到1精通实战(一)
    第二章:String类
    唤醒手腕 2023年 B 站课程 Golang 语言详细教程笔记(更新中)
    java spring cloud 企业工程管理系统源码+二次开发+定制化服务
    【小月电子】安路国产FPGA开发板系统学习教程-LESSON3 LED流水灯
    Java 24 Design Pattern 之
    命令执行相关函数及各类命令执行绕过技巧
    业务网关之AK中心建设
    秋招知识点总结-FPGA基础知识
  • 原文地址:https://blog.csdn.net/weixin_62735525/article/details/127551294