首页 > 编程语言 >Java 自定义注解

Java 自定义注解

时间:2023-12-31 13:37:59浏览次数:21  
标签:Java String 自定义 user 注解 message ElementType public


1. 元注解

元注解是 Java 提供的一些基本注解,使用这些元注解区可疑创建新的注解;可以先大致看一下元注解,然后去看后面自定义注解的例子。

元注解有 @Retention, @Documented, @Target, @Inherited,@Repeatable 五种。

1.1 @Retention

@Retention 可以定义注解的生命周期,注解的存活时间有如下三种:

  • RetentionPolicy.SOURCE: 注解只在源码阶段保留,在编译器完整编译之后,它将被丢弃忽视;

例:@Override,源码如下所示:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
  • RetentionPolicy.CLASS: 注解只被保留到编译进行的时候,注解不会被加载到 JVM 中;
  • RetentionPolicy.RUNTIME: 注解可以保留到程序运行的时候,注解会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。

例: @Service 拥有 @Retention(RetentionPolicy.RUNTIME) 注解,所以在程序运行时可以捕获到它们。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

1.2 @Target

@Target 表示该注解用于什么地方,可以理解为:当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。可以使用的 ElementType 参数:

  • ElementType.CONSTRUCTOR: 对构造方法进行注解;
  • ElementType.ANNOTATION_TYPE: 对注解进行注解;
  • ElementType.FIELD: 对属性、成员变量、成员对象(包括 enum 实例)进行注解;
  • ElementType.LOCAL_VARIABLE: 对局部变量进行注解;
  • ElementType.METHOD: 对方法进行注解;
  • ElementType.PACKAGE: 对包进行注解;
  • ElementType.PARAMETER: 对描述参数进行注解;
  • ElementType.TYPE: 对类、接口、枚举进行注解;

@Override 是 ElementType.METHOD,对方法进行注解;

@Service 是 ElementType.TYPE,对类、接口、枚举进行注解;

1.3 @Documented

@Documented 是一个简单的标记注解,表示是否将注解信息添加在 Java 文档,即 Javadoc 中。

1.4 @Inherited

Inherited 是指继承,@Inherited 定义了一个注释与子类的关系。如果一个超类带有 @Inherited 注解,那么对于该超类,它的子类如果没有被任何注解应用的话,那么这个子类就继承了超类的注解。

1.5 @Repeatable

@Repeatable 是 Java 8 中加入的,是指可重复的意思。通常使用 @Repeatable 的时候指注解的值可以同时取多个。例如:@MapperScan 这个注解。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({MapperScannerRegistrar.class})
@Repeatable(MapperScans.class)
public @interface MapperScan {
    // 略
}

2. 自定义注解

自定义了个 HelloWorld 注解 ,声明注解使用 @ Interface,如下所示。

public @interface HelloWorld

完整的一个注解,注解有两个属性,user 用户,message 名称(默认为helloworld)。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HelloWorld {
    public String user();
    public String message() default "helloWorld";
}

 在方法上标明注解的例子:

public class Main {

    public String user;
    public String message;

    public Main(String user, String message) {
        this.user = user;
        this.message = message;
    }

    @HelloWorld(user="syrdbt", message = "hello world")
    void show() {
        System.out.println("show");
    }

    @HelloWorld(user="syrdbt")
    void show1() {
        System.out.println("show1");
    }

    @Override
    public String toString() {
        return "Main{" +
                "user='" + user + '\'' +
                ", message='" + message + '\'' +
                '}';
    }
}

访问注解:

public class Test {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        // 传入字节码
        trackUseCases(Main.class);
    }

    public static void trackUseCases(Class<?> cl) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        for (Method m : cl.getDeclaredMethods()) {
            // 获得注解的对象
            HelloWorld helloWorld = m.getAnnotation(HelloWorld.class);
            // 访问注解上面的属性
            if (helloWorld != null) {
                System.out.println("Found Use Case:" + helloWorld.user() + " "
                        + helloWorld.message());
            }
        }
    }
}

 运行截图如下所示,可以知道获取注解的属性也不是有序的。

Java 自定义注解_元注解

Java 自定义注解_构造函数_02

3. 使用注解产生一个 bean 

这里使用注解产生一个 bean ,使用从注解的获取属性,然后使用反射获取 Main 类的构造函数,调用构造函数和从注解的获取属性 生成 bean 。

public class Test {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        // 传入字节码
        makeBean(Main.class);
    }

    public static void makeBean(Class<?> cl) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取构造函数
        Constructor<?> constructor = cl.getConstructor(String.class, String.class);
        for (Method m : cl.getDeclaredMethods()) {
            //获得注解的对象
            HelloWorld helloWorld = m.getAnnotation(HelloWorld.class);
            if (helloWorld != null) {
                System.out.println("Found Use Case:" + helloWorld.user() + " "
                        + helloWorld.message());
                // 使用构造函数生成 bean
                Object obj = constructor.newInstance(helloWorld.user(), helloWorld.message());
                System.out.println(obj.toString());
            }
        }
    }
}

运行截图如下所示,可以发现获取注解的属性也不是有序的。

Java 自定义注解_构造函数_03

Java 自定义注解_构造函数_04

参考文献:

标签:Java,String,自定义,user,注解,message,ElementType,public
From: https://blog.51cto.com/xuxiangyang/9047858

相关文章

  • Java 自定义类加载器
    1. 系统类加载器系统提供的类加载器有如下三种:启动类加载器, 扩展类加载器,引用程序类加载器。1.1 启动类加载器启动类加载器(BootstrapClassLoader)负责将存放在<JRE_HOME>\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar......
  • Java递归查询文件下所有的图片,移动到指定文件夹中,分批次建立子文件夹
    1.代码实例将/Users/shiheng/desktop/测试文件目录下的图片(包含子文件夹目录下的图片)移动到了/Users/shiheng/desktop/测试结果目录下,默认不分批次建立子文件夹,重名文件只保存一个,代码如下所示:packagecom.syrdbt.java.study;importjava.io.File;importjava.util.*;/**......
  • 无涯教程-Java 正则 - Matcher reset()函数
    java.util.regex.Matcher.reset()方法重置此匹配器。Matcherreset()-声明publicMatcherreset()Matcherreset()-示例下面的示例显示java.util.regex.Matcher.reset()方法的用法。packagecom.learnfk;importjava.util.regex.Matcher;importjava.util.regex.Pat......
  • 无涯教程-Java 正则 - Matcher int regionStart函数
    java.util.regex.Matcher.regionStart()匹配器区域的起始索引。intregionStart()-声明publicintregionStart()intregionStart()-示例下面的示例显示java.util.regex.Matcher.regionStart()方法的用法。packagecom.learnfk;importjava.util.regex.Matcher;imp......
  • 无涯教程-Java 正则 - String replaceAll(String replacement)函数
    java.util.regex.Matcher.replaceAll(Stringreplacement)方法使用给定的替换字符串替换与该模式匹配的每个子序列。StringreplaceAll-声明publicStringreplaceAll(Stringreplacement)replacement  - 替换字符串。StringreplaceAll-返回值通过用替换字符串替......
  • JavaWebDay10
    开发规范restful表属性状态转换,是一种软件架构风格,注意rest是风格为约定方式可以打破,藐视模块的功能通常使用复数加s,表示此类资源要有一个统一响应数据的格式通常用result实体类来封装当想给参数设置默认值可以使用@requestparam注解后括号接defaultvalue=“1” ......
  • Java 方法
    方法的定义与调用定义:Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法的语法为:修饰符返回值类型方法名(参数类型参数名){ ... 方法体 ... return返回值;}修饰符:可选,告诉编译器如何调用该方法,定义了该方法的访问类型。......
  • 无涯教程-Java 正则 - Matcher static String quoteReplacement(String s)函数
    java.time.Matcher.quoteReplacement(Strings)方法返回指定字符串的文字替换字符串。staticStringquoteReplacement-声明publicstaticStringquoteReplacement(Strings)s  - 要被字符串化的字符串。staticStringquoteReplacement-返回值文字字符串替换。......
  • java的二维数组怎么添加数据
    Java的二维数组怎么添加数据在Java中,二维数组是由多个一维数组组成的,可以看作是一个表格或者矩阵。要向二维数组中添加数据,我们可以使用循环来遍历数组的每个位置,并将数据赋值给对应的元素。创建和初始化二维数组在向二维数组添加数据之前,我们首先需要创建并初始化一个二维数组......
  • java并发调接口
    使用Java并发调接口的步骤流程图flowchartTDStart-->|创建线程池|CreateThreadPoolCreateThreadPool-->|提交任务|SubmitTaskSubmitTask-->|执行任务|ExecuteTaskExecuteTask-->|获取结果|GetResultGetResult-->|处理结果|ProcessResult......