java注解教程 pdf_Java注解详解

在使用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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/571479.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

●BZOJ 1855 [Scoi2010]股票交易

题链: http://www.lydsy.com/JudgeOnline/problem.php?id1855 题解: DP,单调队列优化。(好久没做 DP题,居然还意外地想出来了) 定义 dp[i][k] 表示前 i天,手上还有 k股的最大收益。(注意这个定…

java无权图求最短路径_求有权图和无权图的最短路径

无权图的最短路径思路:无权图的最短路径也就是要求两点之间最少几跳可达,那么我们可以这样,用广度遍历,从起点开始一层层遍历,如果第一次遍历到终点,那么肯定是最短路径。public static void findPath(int …

无限级分类及生成json数据

第一步,先去数据库查询类别数据,然后交给生成json数据的函数处理,代码如下: 1 /*生成类别JSON数据*/ 2 public function wirteJson(){ 3 $dataInfo \think\Db::query("select id as v,name as n,pid from think_pro_category"); 4 $data $this…

python游戏图像识别_利用python做图像识别

Python验证码识别处理实例(转)一、准备工作与代码实例1、PIL、pytesser、tesseract(1)安装PIL:下载地址:http://www.pythonware.com/products/pil/(CSDN下载)下载后是一个exe,直接双击安装,它会自动安装到C:\Python27\Lib\site-pa…

Java旅游动吧项目讲解_springboot动吧项目

架构分析页面流程业务分析:客户端向服务端发送一个请求,发向了Tomcat,如果Tomcat只有一个线程是不可能处理多个请求的,所以就需要一个多个线程的池资源,然后线程用I/O读取请求中的数据,然后服务器从http协议…

java并发-内存模型与volatile

JMM的关键技术点都是围绕着多线程的原子性、可见性和有序性来建立的。因此,我们首先必须了解这些概念 1,原子性 原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰&#xf…

python glob函数_python glob 模块 map函数

昨晚有了点小想法,想写个小脚本。用到了 glob 模块 和 map 函数 觉得他们配合起来和不错的。#coding:utf8import globprint "glob.golb 方法返回 " , glob.glob(r"/var/log/*.log")a glob.iglob(r"/var/log/*.log")print &qu…

数据分析师免费课程网址

分享一些免费的课程以下课程免费,讲师都是领域的专家,需要提前报名,请注意开班的时间。Coursera.org:统计学。Coursera.org:机器学习。Coursera.org:数据分析的计算方法。Coursera.org:大数据。…

微信机器人红包java_微信机器人_奇迹蛋_java实现

【实例简介】参考了别人的一些微信开发方法,自己实现了一个简单的微信机器人,部署在百度云上,能够点歌,查询天气,调教对话。可关注微信公众号:奇迹蛋。实现说明:http://blog.csdn.net/elcarim/a…

python增量赋值是什么意思_关于python中的增量赋值的理解

增量赋值运算符 和 * 的表现取决于它们的第一个操作对象 操作首先会尝试调用对象的 __ iadd__方法,如果没有该方法,那么尝试调用__add__方法,所以 与 的区别实质是__iadd__ 与 __add__的区别,同理,* 操作首先会尝试调…

Notepad++使用教程

Notepad 快捷键 大全CtrlC 复制CtrlX 剪切CtrlV 粘贴CtrlZ 撤消CtrlY 恢复CtrlA 全选CtrlF 键查找对话框启动CtrlH 查找/替换对话框CtrlD 复制并粘贴当行CtrlL 删除当前行CtrlT 当行向上移动一行F3 查找下一个ShiftF3 查找上一个CtrlShiftF 组合在文件中查找CtrlF3 查找&#x…

安卓手机刷软路由_华为路由AX3 Pro上手测评:用过最方便的路由器,没有之一...

都说"科技改变生活",但我总觉着,现如今的人们似乎被数码产品"奴役"了。比如说:之前买过某品牌路由器,设置过程之繁琐,直接让当时是数码小白的我崩溃了。自打那之后,我选购数码产品的标…

ECharts.js学习(二)动态数据绑定

Echarts 数据绑定 简单的统计表已经可以生成,不过之前图标数据都是直接写在参数里面的,而实际使用中,我们的数据一般都是异步读取的。EChart.js对于数据异步读取这块提供了异步加载的方法。 绑定多组数据 很多时候需要展示的数据不单单是一组…

黑苹果2k屏_一加手机屏幕新特性:120Hz、2K+ OLED、10bit

在发布了旗下的首款概念手机Concept One后,再次有消息显示一加将在1月13日也就是今天举办“屏幕技术沟通会”。而在发布会正式到来前,一加CEO刘作虎则在微博表示,一加已经完成了120Hz屏幕的研发。沟通会上还会聊一聊一加90Hz 流体屏引领行业后…

popupmenu java_Java基于JPopupMenu实现系统托盘的弹出菜单,解决PopupMenu弹出菜单中文乱码...

本人萌新,利用业余时间学习Java。最近在写一个GUI程序的时候遇到一个问题,系统托盘创建弹出菜单中文乱码,网上搜索很多内容都没有找到解决方案,现将个人解决方案分享给大家,希望有所帮助一、PopupMenu存在的问题标准文…

QT获取主机名称

//获取主机名 QString localHost QHostInfo::localHostName(); 转载于:https://www.cnblogs.com/amwuau/p/8021758.html

Java哈利波特死亡圣器下_如果编程语言是《哈利波特》中的人物

如果编程语言是《哈利波特》中的人物,本文是作者的一些观点,如果你有不同的看法,欢迎在留言中告诉我们。C语言每个人都在说,C语言已经死了至少十年以上了。人们对它嗤之以鼻。当然它也曾不可一世,肆虐横行,…

序列每天从0开始_【算法打卡】分割数组为连续子序列

难度:中等题目:给你一个按升序排序的整数数组 num(可能包含重复数字),请你将它们分割成一个或多个长度为 3 的子序列,其中每个子序列都由连续整数组成。如果可以完成上述分割,则返回 true ;否则&#xff0c…

linux中 /dev/null命令

/dev/null :代表空设备文件 > :代表重定向到哪里,例如:echo "123" > /home/123.txt1 :表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于"1>/d…

php会员系统源码_b2b2c商城系统会员预存款架构及源码分享

业务需求可以为预存款充值,在支付订单时使用预存款支付功能当预存款余额>商品订单总金额时,完全抵扣商品订单金额;当预存款余额架构一、 充值二、 数据结构1、会员钱包表(es_member_wallet)2、 后期可能会将会员积分等关于消费抵扣相关信息…