• 注解、自定义注解、处理自定义注解


    注解概述

    Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。

    Java 语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注。

    例如:

    1. public class UserServiceTest {
    2. @Test
    3. public void testLogin(){
    4. }
    5. @Test
    6. public void testChu(){
    7. }
    8. }

    注解的作用

    对Java中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定。 例如:JUnit框架中,标记了注解@Test的方法就可以被当成测试方法执行,而没有标记的就不能当成测试方法执行。

    自定义注解

    格式:

    1. public @interface 注解名称 {
    2. public 属性类型 属性名() default 默认值;
    3. }

    特殊属性:

     value属性,如果只有一个value属性的情况下,使用value属性的时候可以省略value名称不写!! 但是如果有多个属性,  且多个属性没有默认值,那么value名称是不能省略的。

    元注解

    元注解:就是注解注解的注解。 

    常见元注解:

    1. @Target: 约束自定义注解只能在哪些地方使用
    2. @Retention:Indicates how long annotations with the annotated type are to be retained. 

    @Target中可使用的值定义在ElementType枚举类中,常用值如下

    1. TYPE,类,接口
    2. FIELD, 成员变量
    3. METHOD, 成员方法
    4. PARAMETER, 方法参数
    5. CONSTRUCTOR, 构造器
    6. LOCAL_VARIABLE, 局部变量

     @Retention中可使用的值定义在RetentionPolicy枚举类中,常用值如下

    1. SOURCE: 注解只在源码中存在,生成的字节码文件中不存在
    2. CLASS: 注解在源码、字节码文件中存在,运行阶段不存在,默认值.
    3. RUNTIME:注解在源码、字节码文件、运行阶段都存在(开发常用)

    注解解析:判断是否存在注解,存在注解就解析出内容。

    与注解解析相关的接口

    Annotation: 注解的顶级接口,注解都是Annotation类型的对象

    AnnotatedElement:代表被注解的元素,该接口定义了与注解解析相关的解析方法

    Annotation[]    getDeclaredAnnotations()获得当前对象上使用的所有注解,返回注解数组。
    T getDeclaredAnnotation(Class annotationClass)根据注解类型获得对应注解对象
    boolean isAnnotationPresent(Class annotationClass)判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false

    所有的类成分Class, Method , Field , Constructor,都实现了AnnotatedElement接口,他们都拥有解析注解的能力。

    解析注解的技巧

    注解在哪个成分上,我们就先拿哪个成分对象。  

    比如注解作用成员方法,则要获得该成员方法对应的Method对象,再来拿上面的注解  

    比如注解作用在类上,则要该类的Class对象,再来拿上面的注解  

    比如注解作用在成员变量上,则要获得该成员变量对应的Field对象,再来拿上面的注解

    注解解析的案例

    • 定义注解Book,要求如下:        

            - 包含属性:String value()   书名        

            - 包含属性:double price()  价格,默认值为 100        

            - 包含属性:String[] authors() 多位作者        

            - 限制注解使用的位置:类和成员方法上        

            - 指定注解的有效范围:RUNTIME

    • 定义BookStore类,在类和成员方法上使用Book注解
    • 定义AnnotationDemo测试类获取Book注解上的数据

    代码:

    1. import java.lang.annotation.ElementType;
    2. import java.lang.annotation.Retention;
    3. import java.lang.annotation.RetentionPolicy;
    4. import java.lang.annotation.Target;
    5. @Target({ElementType.TYPE,ElementType.METHOD})
    6. @Retention(RetentionPolicy.RUNTIME)
    7. public @interface Book {
    8. String value();
    9. double price() default 100;
    10. String[] authors();
    11. }
    1. @Book(value = "xiyojji",price = 99.6,authors = {"aa","b"})
    2. public class BookStore {
    3. @Book(value = "sanguoyanyi",price = 299.6,authors = {"cc","b"})
    4. public String getName(){
    5. return "xx";
    6. }
    7. }
    1. import java.lang.reflect.Method;
    2. import java.util.Arrays;
    3. public class AnnotationDemo {
    4. public static void main(String[] args) throws NoSuchMethodException {
    5. Class bookStoreClass = BookStore.class;
    6. if (bookStoreClass.isAnnotationPresent(Book.class)) {
    7. Book book = bookStoreClass.getAnnotation(Book.class);
    8. System.out.println( book.value());
    9. System.out.println( book.price());
    10. System.out.println(Arrays.toString(book.authors()));
    11. }
    12. Method getName = bookStoreClass.getMethod("getName");
    13. if (getName.isAnnotationPresent(Book.class)) {
    14. Book book = getName.getAnnotation(Book.class);
    15. System.out.println( book.value());
    16. System.out.println( book.price());
    17. System.out.println(Arrays.toString(book.authors()));
    18. }
    19. }
    20. }

    模拟junit框架

    需求

            定义若干个方法,只要加了MyTest注解,就可以在启动时被触发执行

    分析

            定义一个自定义注解MyTest,只能注解方法,存活范围是一直都在。

            定义若干个方法,只要有@MyTest注解的方法就能在启动时被触发执行,没有这个注解的方法不能执行。

    1. import java.lang.annotation.ElementType;
    2. import java.lang.annotation.Retention;
    3. import java.lang.annotation.RetentionPolicy;
    4. import java.lang.annotation.Target;
    5. @Target({ElementType.METHOD})
    6. @Retention(RetentionPolicy.RUNTIME)
    7. public @interface MyTest {
    8. }
    1. public class C {
    2. @MyTest
    3. public void m1(){
    4. System.out.println("m1 invoked");
    5. }
    6. public void m2(){
    7. System.out.println("m2 invoked");
    8. }
    9. @MyTest
    10. public void m3(){
    11. System.out.println("m3 invoked");
    12. }
    13. }
    1. import java.lang.reflect.InvocationTargetException;
    2. import java.lang.reflect.Method;
    3. public class MyJunit {
    4. public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
    5. Class cClass = C.class;
    6. C c = new C();
    7. for (Method method : cClass.getMethods()) {
    8. if (method.isAnnotationPresent(MyTest.class)) {
    9. method.invoke(c);
    10. }
    11. }
    12. }
    13. }
  • 相关阅读:
    设计模式java版本阅读笔记 一结构型
    @Autowired 到底是怎么把变量注入进来的?
    传统关系型数据库(mysql),缓存(redis),elasticsearch
    MATLAB中sos2tf函数用法
    学习ArkTS -- 状态管理
    【无标题】
    LeetCode每日一题——2562. Find the Array Concatenation Value
    VUE2安装初始化步骤(2022)
    中国大模型语料数据联盟迎来9家新成员,开源第二批语料数据
    【JAVA - List】差集removeAll() 四种方法实现与优化
  • 原文地址:https://blog.csdn.net/daqi1983/article/details/133067780