• 猿创征文|Java实现自定义注解


    在这里插入图片描述

    前言

    自定义注解也是一道经常会被问道的面试题.通常会问你自己用过自定义注解吗,让你简单描述下原理,相信如果你写过一次,就能简单的回答出一些问题

    注解的作用

    像平时用到的 SpringBoot、Mybatis 等框架提供了许多的注解,免去了许多配置文件的繁琐工作,大大简便了开发,Java 提供了自定义注解的功能,这里就先展示简单的例子。

    注解可以看作是一种特殊的标记,可以用在方法、类、参数和包上,程序在编译或者运行时可以检测到这些标记而进行一些特殊的处理,例如标注在方法上可以实现接口权限的校验。

    使用场景:自定义注解+拦截器或者 AOP。

    声明方式:通过关键字 @interface 声明为注解,例子如下:

    public @interface MyAnnotation{
        
    }
    
    
    • 1
    • 2
    • 3
    • 4

    注解的元素类型

    主要有@Target,@Retention,@Document,@Inherited 用来修饰注解。

    @Target常用属性

    表明该注解可以应用的java元素类型。

    Target类型描述
    ElementType.TYPE应用于类、接口(包括注解类型)、枚举
    ElementType.FIELD应用于属性(包括枚举中的常量)
    ElementType.METHOD应用于方法
    ElementType.PARAMETER应用于方法的形参
    ElementType.CONSTRUCTOR应用于构造函数
    ElementType.LOCAL_VARIABLE应用于局部变量
    ElementType.ANNOTATION_TYPE应用于注解类型
    ElementType.PACKAGE应用于包
    ElementType.TYPE_PARAMETER1.8版本新增,应用于类型变量
    ElementType.TYPE_USE1.8版本新增,应用于任何使用类型的语句中(例如声明语句、泛型和强制转换语句中的类型)

    @Retention

    表明该注解的生命周期。

    生命周期类型描述
    RetentionPolicy.SOURCE编译时被丢弃,不包含在类文件中
    RetentionPolicy.CLASSJVM加载时被丢弃,包含在类文件中,默认值
    RetentionPolicy.RUNTIME由JVM 加载,包含在类文件中,在运行时可以被获取到

    @Documented

    表明该注解标记的元素可以被Javadoc 或类似的工具文档化。

    @Inherited

    表明使用了@Inherited注解的注解,所标记的类的子类也会拥有这个注解

    代码实现自定义注解

    光说没用,接下来我们实际操作一遍,就能简单感受到自定义注解的作用

    1 编写自定义注解

    package com.example.annotation;
    
    import java.lang.annotation.*;
    
    /**
     * @description: 自定义注解
     * @author: 魏一鹤
     * @createDate: 2022-08-30 23:04
     **/
    
    //该注解可以应用于类、接口(包括注解类型)、枚举
    @Target(ElementType.TYPE)
    //该注解标记的元素可以被Javadoc 或类似的工具文档化
    @Documented
    //该注解的生命周期,由JVM 加载,包含在类文件中,在运行时可以被获取到
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MyAnnotation {
        // 给自定义注解创建基本属性
        // 可以使用default作为默认值使用
        String name() default "法外狂徒张三";
        // 这里没用default默认赋值,一会手动复制
        int age() ;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2 编写实体

    package com.example.entity;
    
    import com.example.annotation.MyAnnotation;
    import lombok.Data;
    
    /**
     * @description: 用户实体类
     * @author: 魏一鹤
     * @createDate: 2022-08-30 23:06
     **/
    
    @Data
    // 把我们自定义的注解作用到user类上
    @MyAnnotation(age = 18)
    public class User {
        String name;
        int age;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3 编写测试代码

    package com.example.test;
    
    import com.example.annotation.MyAnnotation;
    import com.example.entity.User;
    
    /**
     * @description: 测试自定义注解
     * @author: 魏一鹤
     * @createDate: 2022-08-30 23:09
     **/
    
    public class AnnotationTest {
        public static void main(String[] args){
            //获取User的Class对象
            Class<?> userClass = User.class;
            //判断Class对象上是否有我们设置的自定义注解
            if (userClass.isAnnotationPresent(MyAnnotation.class)) {
                System.out.println("User上配置了自定义注解");
                //获取SystemConfig注解
                MyAnnotation myAnnotation = userClass.getAnnotation(MyAnnotation.class);
                System.out.println("MyAnnotation.name:" + myAnnotation.name() + "; MyAnnotation.age:" + myAnnotation.age());
            } else {
                System.out.println("User上没有配置自定义注解");
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    4 测试效果

    首先我们给User实体加上我们的自定义注解,可以看到,成功的通过注解获取到了属性
    在这里插入图片描述
    然后我们给User实体去掉自定义注解 再次运行 很明显,是获取不到注解的属性的
    在这里插入图片描述

    结语

    至此 一个简单的自定义注解Demo就完成了

    如果我们的注解写的比较好的话,对于性能有较大的影响,可用于软件的架构设计,实现动态加载,对于分解复杂业务有帮助。

  • 相关阅读:
    stm32f334定时器配置详细解释
    [技术选型与调研] 流程引擎(工作流引擎|BPM引擎):Activiti、Flowable、Camunda
    支持JDK19虚拟线程的web框架,之三:观察运行中的虚拟线程
    sort by 和 order by 的区别
    K8s学习笔记——资源组件篇
    将 Cloudflare 页面与 IPFS 结合使用
    CISAW信息安全保障人员-应急管理
    基于SSM的公司项目管理系统设计与实现
    【题解】剑指 Offer 07. 重建二叉树
    Jupyter notebook如何把一行里面所有代码都复制到pycharm里面,而不用一哥代码块,也就是一个cells得复制。直接全部或者多个复制代码
  • 原文地址:https://blog.csdn.net/weixin_46713508/article/details/126614878