框架开发之Java注解的妙用(下)

简介: 框架开发之Java注解的妙用(下)

2)Java第三方注解


image.png


二、注解的分类


1)按照运行机制划分:


【源码注解→编译时注解→运行时注解】


源码注解:只在源码中存在,编译成.class文件就不存在了。


编译时注解:在源码和.class文件中都存在。像前面的@Override、@Deprecated、@SuppressWarnings,他们都属于编译时注解。


运行时注解:在运行阶段还起作用,甚至会影响运行逻辑的注解。像@Autowired自动注入的这样一种注解就属于运行时注解,它会在程序运行的时候把你的成员变量自动的注入进来。


2)按照来源划分:


【来自JDK的注解——来自第三方的注解——自定义注解】

3)元注解:


元注解是给注解进行注解,可以理解为注解的注解就是元注解。


三、自定义注解


我们分四步来解析自定义注解:


自定义注解的语法要求:


@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description {
    String desc();
    String author();
    int age() default 18;
}


首先我们要明确这不是一个接口,它是使用@interface关键字定义的一个注解。

然后我们看下面的几个方法,String desc();虽然它很类似于接口里面的方法,其实它在注解里面只是一个成员变量(成员以无参无异常的方式声明),int age() default 18;(成员变量可以用default指定一个默认值的)。

最后我们要知道:

①.成员类型是受限制的,合法的类型包括基本的数据类型以及String,Class,Annotation,Enumeration等。

②.如果注解只有一个成员,则成员名必须取名为value(),在使用时可以忽略成员名和赋值号(=)。

③.注解类可以没有成员,没有成员的注解称为标识注解。


元注解:


有没有发现上面那段代码有一个没有说呢?没错,它们就是我们所说的元注解:


@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented


我们先看第一行:@Target是这个注解的作用域,ElementType.METHOD是这个注解的作用域的列表,METHOD是方法声明,除此之外,还有:


CONSTRUCTOR(构造方法声明),FIELD(字段声明),LOCAL VARIABLE(局部变量声明),METHOD(方法声明),PACKAGE(包声明),PARAMETER(参数声明),TYPE(类接口)


第二行:@Retention是它的生命周期,前面不是说注解按照运行机制有一个分类嘛,RUNTIME就是在运行时存在,可以通过反射读取。除此之外,还有:


SOURCE(只在源码显示,编译时丢弃),CLASS(编译时记录到class中,运行时忽略),RUNTIME(运行时存在,可以通过反射读取)


第三行:@Inherited是一个标识性的元注解,它允许子注解继承它。


第四行:@Documented,生成javadoc时会包含注解。


使用自定义注解:


使用注解的语法:


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


案例:


  @Description(desc="i am Color",author="boy",age=18)
    public String Color() {
        return "red";
    }


这里的Description是我们刚才在自定义注解语法要求里面定义的注解噢,然后我们可以给它的每一个成员变量赋值,注意数据类型。值得注意的是,因为我们前面定义的作用域是在方法和类接口上,所以这个注解在Color()方法上使用是没问题的。

解析注解

概念:

通过反射获取类 、函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑。


准备工作:


image.png


image.png


接下来,我们就开始测试了:


public class ParseAnn {
    public static void main(String[] args) {
        try {
            // 使用类加载器加载类
            Class c = Class.forName("com.test.Child");
            // 找到类上面的注解
            boolean isExist = c.isAnnotationPresent(Description.class);
            // 上面的这个方法是用这个类来判断这个类是否存在Description这样的一个注解
            if (isExist) {
                // 拿到注解实例,解析类上面的注解
                Description d = (Description) c.getAnnotation(Description.class);
                System.out.println(d.value());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}



输出的结果:

i am class annotation

可以看到,我们成功的解析了Child类上面的注解。

接下来,我们继续解析方法上的注解:


   //获取所有的方法
            Method[] ms = c.getMethods();
            // 遍历所有的方法
            for (Method m : ms) {
                boolean isExist1 = m.isAnnotationPresent(Description.class);
                if (isExist1) {
                    Description d1=m.getAnnotation(Description.class);
                    System.out.println(d1.value());
                }
            }


输出的结果:

i am class annotation

i am method annotation

可以看到,我们成功的解析了方法上面的注解。


   //另一种解析方法
            for (Method m : ms) {
                //拿到方法上的所有的注解
                Annotation[] as=m.getAnnotations();
                for (Annotation a : as) {
                    //用二元操作符判断a是否是Description的实例
                    if (a instanceof Description) {
                        Description d=(Description) a;
                        System.out.println(d.value());
                    }
                }
            }


也可以得到上面的效果。

此时,如果把Description类里面的元注解改一下,比如:

@Retention(RetentionPolicy.RUNTIME)→@Retention(RetentionPolicy.SOURCE),再运行程序,结果会成怎样呢?如果改成CLASS呢?读者们要不要试一试?

如果看过我写的《谈谈JAVA反射机制》——Class类的动态加载的读者,仔细想一下我们这个环境,就知道为什么了。


原文链接:https://www.jianshu.com/p/b560b30726d4


目录
相关文章
|
16天前
|
监控 JavaScript 前端开发
《理解 WebSocket:Java Web 开发的实时通信技术》
【4月更文挑战第4天】WebSocket是Java Web实时通信的关键技术,提供双向持久连接,实现低延迟、高效率的实时交互。适用于聊天应用、在线游戏、数据监控和即时通知。开发涉及服务器端实现、客户端连接及数据协议定义,注意安全、错误处理、性能和兼容性。随着实时应用需求增加,WebSocket在Java Web开发中的地位将更加重要。
|
22小时前
|
Java Maven 开发工具
《Java 简易速速上手小册》第5章:Java 开发工具和框架(2024 最新版)
《Java 简易速速上手小册》第5章:Java 开发工具和框架(2024 最新版)
6 1
|
1天前
|
前端开发 Java Go
开发语言详解(python、java、Go(Golong)。。。。)
开发语言详解(python、java、Go(Golong)。。。。)
|
2天前
|
人工智能 前端开发 Java
Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码
智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应病症信息和推荐就医科室。
27 10
|
2天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
5天前
|
Java 大数据 云计算
Spring框架:Java后台开发的核心
【4月更文挑战第15天】Spring框架在Java后台开发中占据核心位置,因其控制反转(IoC)、面向切面编程(AOP)、事务管理等特性提升效率和质量。Spring提供数据访问集成、RESTful Web服务和WebSocket支持。优势包括高效开发、灵活扩展、强大生态圈和广泛应用。应用于企业级应用、微服务架构及云计算大数据场景。掌握Spring对Java开发者至关重要。
|
7天前
|
存储 Java 编译器
Java集合丛林:深入了解集合框架的秘密
Java集合丛林:深入了解集合框架的秘密
14 0
Java集合丛林:深入了解集合框架的秘密
|
9天前
|
运维 NoSQL 算法
Java开发-深入理解Redis Cluster的工作原理
综上所述,Redis Cluster通过数据分片、节点发现、主从复制、数据迁移、故障检测和客户端路由等机制,实现了一个分布式的、高可用的Redis解决方案。它允许数据分布在多个节点上,提供了自动故障转移和读写分离的功能,适用于需要大规模、高性能、高可用性的应用场景。
16 0
|
11天前
|
人工智能 小程序 Java
JAVA开发智慧学校系统源码+人脸电子班牌布局
智慧校园是通过利用物联网,大数据技术来改变师生和校园资源相互交互的方式,以便提高交互的明确性、灵活性和响应速度,从而实现智慧化服务和管理的校园模式。
|
11天前
|
存储 Java 数据库连接
java使用mp持久化框架,写入5000个字符,但是VARCHAR(255) 会报错
使用Java的MyBatis Plus框架时,如果尝试将超过VARCHAR(255)限制的字符串(如5000个字符)存入数据库,会抛出异常。解决方法是将列类型改为TEXT。可通过在实体类属性上添加`@TableField(typeHandler = JdbcType.CLOB)`注解,如`private String content;`,将属性映射到CLOB类型列,以存储更长字符串。
9 0