说说 Java 注解

作者: deniro | 来源:发表于2018-06-21 16:01 被阅读43次

    Java 注解可以看做是 Javadoc 和 Xdoclet 标签的延伸和发展,我们可以自定义注解标签,并通过 Java 语言的反射机制来获取类中标注的注解,完成特定的功能 。

    注解是代码的附属信息,无论增加还是删除注解,都不会影响程序代码的运行。因为 Java 语言解释器会忽略这些注解,而让第三方工具负责对注解进行处理 。 第三方工具可以利用代码中的注解间接控制程序代码的运行,它们通过 Java 反射机制读取注解的信息,并根据这些信息更改逻辑 。

    1 定义

    我们使用 @interface 来定义注解类。

    示例:

    @Retention(RetentionPolicy.RUNTIME)//保留期限
    @Target(ElementType.METHOD)//目标类型
    public @interface Log {
        boolean value() default true;//声明成员变量
    }
    

    示例中的 @Retention@Target 被称为元注解(Meta-annotation)。

    1.1 成员变量

    可以在注解类中定义多个成员变量,成员变量的定义语法有以下这些要求:

    • 不能定义入参。
    • 不能抛出异常。
    • 可以通过 default 定义一个默认值。
    • 合法的成员类型有这些 - 原始类型及其封装类、Class、enums、注解类型和包含上述类型的数组类型。
    • 如果注解类只有一个成员变量,那么必须名为 value()。在使用时可以忽略成员名称和赋值符号(=),比如可以这样使用示例中的注解 @Log(true)
    • 如果注解类拥有多个成员变量,如果仅对 value 进行赋值,则也可以忽略成员名称和赋值符号(=)。
    • 如果注解类拥有多个成员变量,又需要同时对多个成员变量进行赋值,那么就必须使用成员名称加赋值号表示,比如事务注解:@Transactional(propagation= Propagation.MANDATORY,isolation= Isolation.DEFAULT)
    • 注解类可以没有成员变量,这样注解类被称为标注注解,由调用程序负责判断处理。
    • 注解类不能继承其它类,也不能实现其它接口。

    1.2 保留期限 @Retention

    @Retention 表示保留期限,它被定义在 java.lang.annotation.RetentionPolicy 中:

    保留期限类型 说明
    SOURCE 注解信息仅保留在源代码文件中。
    CLASS 注解信息保留在源代码文件与字节码文件中。
    RUNTIME 注解信息不仅保留在源代码文件与字节码文件中,而且会被加载到 JVM 中,在运行期可以通过反射读取这些注解信息。

    1.3 目标类型 @Target

    @Target 表示注解的应用目标类型。它被定义在 java.lang.annotation.ElementType 中。

    目标类型 说明
    TYPE 类、接口、注解类型、Enum 处声明。
    FIELD 成员变量、Enum 常量处声明。
    METHOD 方法处声明。
    PARAMETER 参数处声明。
    CONSTRUCTOR 构造函数处声明。
    LOCAL_VARIABLE 局部变量处声明。
    ANNOTATION_TYPE 注解类处声明。
    PACKAGE 包处声明。
    TYPE_PARAMETER 类型参数处声明。(1.8 新增)
    TYPE_USE 使用类型处声明。(1.8 新增)

    2 配置注解

    public class User {
    
        @Log()
        public void rent(String userId) {
            System.out.println("User:租赁【充电宝】");
        }
    
        @Log(false)
        public void back(String userId){
            System.out.println("User:归还【充电宝】");
        }
    }
    

    这里直接在需要的方法上,加入注解类。

    标注注解的格式为:

    @<注解名>(<成员名1>=<成员值1>,<成员名2>=<成员值2>,...)
    

    如果成员变量是数组类型,就可以通过{} 进行赋值。

    说明 示例
    单成员注解 @Service("userService")
    多成员注解 @Transactional(propagation= Propagation.MANDATORY,isolation= Isolation.DEFAULT)
    无成员注解 @Override
    成员类型为普通数组 @SuppressWarnings(value={"unchecked", "rawtypes"})
    成员类型为注解数组 @ComponentScans({@ComponentScan("1.xml"),@ComponentScan("2.xml")})

    3 获取注解

    对于保留期限为 RetentionPolicy.RUNTIME 的注解,可以通过反射来获取注解信息 。

    在 Java5.0 中, Package、Class、Constructor、Method 以及 Field 等反射对象都新增了访问注解的多种方法,它们都支持泛型。

    Class clazz = User.class;
    Method[] methods = clazz.getDeclaredMethods();
    for (Method method : methods) {
        //获取注解
        Log log = method.getAnnotation(Log.class);
        if (log != null) {
            if (log.value()) {
                System.out.println(method.getName() + "() 方法需要记录日志");
            } else {
                System.out.println(method.getName() + "() 方法不需要记录日志");
            }
        }
    }
    

    输出结果:

    back() 方法不需要记录日志
    rent() 方法需要记录日志

    是不是很简单呀 O(∩_∩)O哈哈~

    相关文章

      网友评论

        本文标题:说说 Java 注解

        本文链接:https://www.haomeiwen.com/subject/kiwqyftx.html