在使用SpringBoot作为Web敏捷开发的框架之后,SpringBoot除了自动装配配置的便捷之外,在很多时候需要基于注解来开发。注解不仅增加了代码的可读性,还增加了开发的速度。这篇文章主要讲述Java 注解。

元注解

元注解用于注解其他注解的。Java 5.0定义了4个标准的元注解,如下:

@Target

@Retention

@Documented

Inherited

现在来说说这四个元注解有什么作用。

@Target

@Target注解用于声明注解的作用范围,例如作用范围为类、接口、方法等。它的取值以及值所对应的范围如下:

CONSTRUCTOR:用于描述构造器

FIELD:用于描述域

LOCAL_VARIABLE:用于描述局部变量

METHOD:用于描述方法

PACKAGE:用于描述包

PARAMETER:用于描述参数

TYPE:用于描述类、接口(包括注解类型) 或enum声明

@Retention

该注解声明了注解的生命周期,即注解在什么范围内有效。

SOURCE:在源文件中有效

CLASS:在class文件中有效

RUNTIME:在运行时有效(即运行时保留)

大多数注解都为RUNTIME

@Documented

是一个标记注解,有该注解的注解会在生成 java 文档中保留。

@Inherited

该注解表明子类是有继承了父类的注解。比如一个注解被该元注解修饰,并且该注解的作用在父类上,那么子类有持有该注解。如果注解没有被该元注解修饰,则子类不持有父类的注解。

自定义注解

在Java开发者,JDK自带了一些注解,在第三方框架Spring 带了大量的注解,这些注解称为第三方注解。在很多实际开发过程中,我们需要定义自己的注解。那么现在以案例的方式来讲解自定义注解。

在注解中,需要使用四种元注解来声明注解的作用范围、生命周期、继承,是否生成文档等。另外在注解中也可以有自己的成员变量,如果一个注解没有成员变量则称为标记注解。注解的成员变量,只支持原始类型、Class、Enumeration、Annoation。

现在定义一个@Writer注解,该注解被Retention、Documented、Inherited、Target修饰,表明该注解的作用范围为类、接口和方法,生命周期为运行时、该注解生成文档,并且子类可继承该注解。该注解有2个成员变量,一个为name一个为 age,代码如下:

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@Target({ElementType.TYPE,ElementType.METHOD})

public @interface Writer {

String name();

int age();

}

那么有了该注解,怎么用呢?

该注解的作用范围为类、方法,写一个WriterTest,代码如下:

@Writer(name = "forezp", age = 12)

public class WriterTest {

@Writer(name = "miya", age = 10)

public void writeBlog() {

System.out.println("writing blog");

}

}

该类有了这个注解有何用?

一般来说,用该类修饰的类,需要通过反射来做一下逻辑的开发的工作,可广泛用于AOP、程序的配置等。现在写一个方法通过反射来解析该注解:

public static void main(String[] args) throws ClassNotFoundException {

Class c = Class.forName("com.forezp.annotation.WriterTest");

if (c.isAnnotationPresent(Writer.class)) {

Writer w = (Writer) c.getAnnotation(Writer.class);

System.out.println("name:" + w.name() + "   age:" + w.age());

}

Method[] methods = c.getMethods();

for (Method method : methods) {

if (method.isAnnotationPresent(Writer.class)) {

Writer w = method.getAnnotation(Writer.class);

System.out.println("name:" + w.name() + "   age:" + w.age());

}

}

}

这些代码基本为反射的内容,因为反射在另一篇文章已经详细讲述过,不再重复,运行该Main方法,控制台打印出如下内容:

name:forezp age:12

name:miya age:10

案例实战

有了上述的讲解,你可能对注解有所了解,但是对注解的具体应用并不是很深刻。现在以一个案例来详细讲述。

大家都对ORM框架Mybitis都非常的熟悉,在这个框架中用了大量的注解。现在模仿这个框架,通过自定义注解,来解析sql 的查询语句。实现过程大概如下:

定义@Table @Colum注解

定义一个实体User,定义一些基本的字段,并用注解修饰

用User类new对象,给对象的某些字段赋值

通过反射和注解来生成sql 的查询语句

首先定义个一个Table注解,它的作用范围为类,代码如下:

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.TYPE)

@Documented

@Inherited

public @interface Table {

String value() default "";

}

定义一个Column注解,作用范围为字段,代码如下:

@Target(ElementType.FIELD)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

public @interface Column {

String value();

}

定义一个User类,在该类的加上@Table注解,在具体的字段上 @Column注解,代码如下:

@Table("user")

public class User {

@Column("id")

private int id;

@Column("name")

private String name;

@Column("age")

private int age;

@Column("address")

private String address;

..//省略getter setter

}

写一个生成sql语句的类,它是通过反射来获取表名、字段名,加上判断实体对象的字段值来生成 查询的 sql 语句的。代码如下:

public class GenUserSql {

public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {

User u1 = new User();

User u2 = new User();

u1.setId(1);

u2.setName("forezp");

genSql(u2);

genSql(u1);

}

private static void genSql(User user) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

Class c = user.getClass();

StringBuilder stringBuilder = new StringBuilder();

stringBuilder.append("select * from ");

if (c.isAnnotationPresent(Table.class)) {

Table table = (Table) c.getAnnotation(Table.class);

String tableName = table.value();

stringBuilder.append(tableName).append(" where 1=1 and ");

}

Field[] fields = c.getDeclaredFields();

for (Field field : fields) {

String columnName;

if (field.isAnnotationPresent(Column.class)) {

Column column = field.getAnnotation(Column.class);

columnName = column.value();

} else {

continue;

}

String fieldName = field.getName();

String getMethodName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

Method method = c.getMethod(getMethodName);

Object fieldValue = method.invoke(user);

if (fieldValue == null || ((fieldValue instanceof Integer) && (Integer) fieldValue == 0)) {

continue;

}

if (fieldValue instanceof Integer) {

stringBuilder.append(columnName + "=" + fieldValue);

}

if (fieldValue instanceof String) {

stringBuilder.append(columnName + "=" + "'" + fieldValue + "'");

}

}

System.out.println(stringBuilder.toString());

}

}

运行程序,控制台打印如下:

select * from user where 1=1 and name=‘forezp’

select * from user where 1=1 and id=1

java注解教程 pdf_Java注解详解相关推荐

  1. java注解教程 pdf_Java注解教程和自定义注解

    Java注解提供关于代码的信息,并且对它们注解的代码没有直接的影响.在这篇教程中,我们将学习Java注解,如何自定义注解,注解用法和如何使用反射解析注解. Java注解在Java1.5被引用并且在一些 ...

  2. java注解教程 pdf_Java注解教程和示例

    Java注解教程和示例 塔尼亚·辛格 Java注解使我们可以将元数据信息添加到源代码中,尽管它们不是程序本身的一部分.注解是从JDK 5添加到Java的.注解对其注解的代码的操作没有直接影响(即,它不 ...

  3. java注解式开发_JAVA语言之Spring MVC注解式开发使用详解[Java代码]

    本文主要向大家介绍了JAVA语言的Spring MVC注解式开发使用详解,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. MVC注解式开发即处理器基于注解的类开发, 对于每一个定义的处 ...

  4. java jsonfield_关于fastjson的@JSONField注解的一些问题(详解)

    @jsonfield 看源码它可以作用于字段和方法上. 引用网上说的, 一.作用field @jsonfield作用在field时,其name不仅定义了输入key的名称,同时也定义了输出的名称. 但是 ...

  5. 一对一关联查询注解@OneToOne的实例详解(一)

    转载自: https://www.cnblogs.com/boywwj/p/8092915.html 一对一关联查询注解@OneToOne的实例详解 表的关联查询比较复杂,应用的场景很多,本文根据自己 ...

  6. java基础与案例开发详解 pdf下载_Java基础与案例开发详解(张孝祥) pdf_IT教程网...

    资源名称:Java基础与案例开发详解(张孝祥) pdf 第1.2和3章介绍Java环境的安装配置,Java程序的开发过程和Java语言的基础语法. 第4章介绍数组和常用算法的相关知识. 第5章和6章介 ...

  7. Java基础教程:注解

    Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...

  8. java委托机制教程_通过反射实现Java下的委托机制代码详解

    简述 一直对java没有现成的委托机制耿耿于怀,所幸最近有点时间,用反射写了一个简单的委托模块,以供参考. 模块api public class delegater()//空参构造,该类管理委托实例并 ...

  9. tcp网络通信教程 java_基于java TCP网络通信的实例详解

    JAVA中设计网络编程模式的主要有TCP和UDP两种,TCP是属于即时通信,UDP是通过数据包来进行通信,UDP当中就会牵扯到数据的解析和传送.在安全性能方面,TCP要略胜一筹,通信过程中不容易出现数 ...

最新文章

  1. mxnet中symbol的网络结构输出(参数维度,和每层输出维度)
  2. mysql远程主机强迫关闭了一个现有连接_asp.net连接mysql出现了远程主机强迫关闭了一个现有的连接。!!!...
  3. 三台机器之间root用户ssh互信配置
  4. 诺基亚力邀App开发员加入Ovi以对抗苹果
  5. 解决配置shiro+jwt后swagger接口文档无法访问的问题
  6. 【 HDU - 5459】Jesus Is Here(dp)
  7. js距离单位换算_英语中常用的度量衡等单位,与我们用的不一样,这些差异点快收藏...
  8. python高阶函数(三分钟读懂)
  9. 【WPF】如何获取命令行参数
  10. 网络规划设计师考点总结
  11. 远离奸商-查看CPU信息是否被修改
  12. 2021级《高级语言》重现 F 方阵
  13. C语言编程练习题_02兰州烧饼
  14. uni-app中的生命周期钩子函数
  15. 成功路上并不拥挤 因为坚持的人不多
  16. ORA-01045: user ICCS lacks CREATE SESSION privilege; logon denied
  17. C语言编程>第二十二周 ⑥ 请补充fun函数,该函数的功能是:把字符下标能被2和3同时整除的字符从字符串s中删除,把剩余的字符重新保存在字符串s中。
  18. 勾股定理的证明(转载)
  19. html加css加js制作的烟花,js实现烟花特效
  20. 谷粒学院笔记-第二天-数据库设计

热门文章

  1. HTML+CSS+JS实现 ❤️透明等离子球ui特效❤️
  2. oracle 解死锁权限,讲解Oracle数据库中结束死锁进程的一般方法
  3. 自动填充html_第 11 篇:自动生成文章摘要
  4. android 字符串调用方法名,AndroidJNI.CallStringMethod 调用字符串方法
  5. php开发添加表情功能,WordPress网站评论区如何实现添加表情包功能?
  6. java怎编写么解析一个类型_DAY3:你必须知道的java虚拟机之类篇——类文件的结构...
  7. Python入门基础篇(二)元组,更适合新手哦!!!
  8. dsp实现快速傅里叶的C语言程序,DSP-快速傅立叶变换(FFT)算法实验
  9. oracle 表访问,向oracle导入访问表
  10. 电气专业学python吗_985大学毕业起薪最高的五个专业,计算机、金融、电气上榜!...