Java注解annotation用法和自定义注解处理器
前言:
在J2EE中,注解使得开发更加便利,省去了生成XML文件的过程,在Hibernate实体声明中,可以简简单单的用几个注解就可以免去生成一个XML的文件操作。这里就主要论述一下annotation的用法和自定义注解处理器。当在创建描述符性质的类或接口时,有大量重复性的工作时候,就可以利用注解来实现。
基本语法:
Java目前包括三种标准注解和四种元注解。元注解主要负责注解其他注解的。
三种标准注解:
@Override,表示当前的方法定义覆盖了父类中的方法。必须要有相同的方法签名即(方法名,参数类型,参数顺序,参数个数)都一样。否则在编译过程中发出错误提示。
@Deprecated,对不应该再使用的方法添加注解,当使用这个方法的时候,会在编译时候显示提示信息。
@SuppressWarnings,关闭不当的编译器报警信息
四种元注解:
@Target,表示该注解可以用什么地方。
如CONSTRUCTOR,构造器声明;FIELD,域声明;METHOD,方法声明;TYPE,类,接口或enum声明
@Retention,表示需要在什么级别保存该注解信息。
如SOURCE,注解将被编译器丢弃;CLASS,注解在class文件可用,但会被VM丢弃
RUNTIME,VM将在运行期间也保留注解,可以使用反射机制读取注解信息
@Documented,将此注解包含到Javadoc中。
@Inherited,允许子类继承父类的注解。
定义注解:
自定义注解是以@interface为标志的。如同一个接口的定义,这里面定义的每个方法名,就是使用注解时候的元素名,方法的返回值就是元素的类型,可以利用default来声明默认值,不过对于非基本类型,不能设置为null为默认值,一般对于字符串使用空字符串作为其默认值。
如下所示:
package whut.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//定义一个注解
@Target(ElementType.METHOD)//定义该注解将应用于什么地方,方法或者域
@Retention(RetentionPolicy.RUNTIME)//定义该注解在哪一个级别可用
public @interface UseCase {
//注解元素,可以指定默认值,在使用注解的时候,可以直接给元素赋值如id=5
public int id();
public String description() default "no description";
//利用枚举来设置参数类型
public enum ParameterType { STRING, SHORT, INT, BOOL, LONG, OBJECT };
// 默认值,在使用注解的时候,只需要为元素赋值
public ParameterType type() default ParameterType.STRING;
}
使用注解:
在类中任意的域值前,或者方法前等直接@注解名,如@UseCase(id=5),使用注解的过程中,必须对于没有设置默认值的元素进行赋值操作,对于每个元素进行按照名-值对的方式赋值。如果在注解定义中有名为value的元素,并且它是唯一需要赋值的,可以直接在括号里给出value所需要的值。
注解是不能继承的。
下面是一个基本的利用非apt实现的注解处理器模型。
这个模型可以注解实体,进行数据库的映射建表操作。是最最基本的操作。
注解定义:将四个注解名是在不同的文件中。
package whut.annotationDB;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
//定义字段的约束
public @interface Constraints {
boolean primaryKey() default false;
boolean allowNull() default true;
boolean unique() default false;
}
////////////////////////////
package whut.annotationDB;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)//类,接口或enum
@Retention(RetentionPolicy.RUNTIME)
//定义表名的注解
public @interface DBTable {
public String name() default "";
}
///////////////////////////
package whut.annotationDB;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)//类,接口或enum
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLInteger {
String name() default "";
//嵌套注解的功能,将column类型的数据库约束信息嵌入其中
Constraints constraints() default @Constraints;
}
///////////////////////////////
package whut.annotationDB;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)//类,接口或enum
@Retention(RetentionPolicy.RUNTIME)
public @interface SQLString {
int value() default 0;
String name() default "";
//注解元素中引用别的注解,
Constraints constraints() default @Constraints;
}
实体使用注解:这里是运用了运行时候处理注解,所以RetentionPolicy.RUNTIME
package whut.annotationDB;
@DBTable(name="MEMBER")
public class Member {
//在使用注解过程中,如果有元素是value,并且只有value需要赋值,
//则只需要在()中将值写入
@SQLString(30)
private String firstName;
@SQLString(50)
private String lastName;
@SQLInteger
private Integer age;
@SQLString(value=30,constraints=@Constraints(primaryKey=true))
private String handle;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getHandle() {
return handle;
}
public void setHandle(String handle) {
this.handle = handle;
}
}
具体的非apt实现的注解处理器:
package whut.annotationDB;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class TableCreator {
public Connection getConnection() {
String user = "root";
String password = "";
String serverUrl = "jdbc:mysql://localhost:3306/carrent?user=root&password=";
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection(serverUrl, user,
password);
return con;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//实现创建表
public static void main(String[] args) {
TableCreator tc = new TableCreator();
tc.executeCreateDB(Member.class);
}
public void executeCreateDB(Class<?> entity) {
String sqlStr = explainAnnotation(entity);
Connection con = getConnection();
PreparedStatement psql = null;
if (con != null && !sqlStr.equals("error")) {
try {
psql = con.prepareStatement(sqlStr);
psql.execute();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (psql != null)
psql.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con != null)
psql.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} else
System.out.println("failure to...");
}
// 真正的处理器,Class<?>必须用这个表明
public String explainAnnotation(Class<?> entity) {
// 获取指定类型的注解
DBTable dbtable = entity.getAnnotation(DBTable.class);
if (dbtable == null) {
System.out.println("No DBTable annotation in class"
+ entity.getName());
return "error";
} else {
String tableName = dbtable.name();// 获取注解name值,即表名称
// 当没有设置name值,直接利用类的名作为表名
if (tableName.length() < 1)
tableName = entity.getName().toUpperCase();// 转换大写
// 准备处理字段注解
List<String> columnsDefs = new ArrayList<String>();
// 获取该类的所有字段
for (Field field : entity.getDeclaredFields()) {
String columnName = null;
// 获取该字段所有的注解
Annotation[] anns = field.getDeclaredAnnotations();
// Annotation[] anns=field.getAnnotations();
// 当有注解的时候
if (anns.length >= 1) {
// 判断注解的类型
if (anns[0] instanceof SQLInteger) {
SQLInteger sInt = (SQLInteger) anns[0];
// 当没有name时候,将字段大写为列名
if (sInt.name().length() < 1)
columnName = field.getName().toUpperCase();
else
columnName = sInt.name();
columnsDefs.add(columnName + " INT"
+ getConstraints(sInt.constraints()));
}
if (anns[0] instanceof SQLString) {
SQLString sString = (SQLString) anns[0];
// 当没有name时候,将字段大写为列名
if (sString.name().length() < 1)
columnName = field.getName().toUpperCase();
else
columnName = sString.name();
columnsDefs.add(columnName + " VARCHAR("
+ sString.value() + ")"
+ getConstraints(sString.constraints()));
}
}
}
StringBuilder createDB = new StringBuilder("CREATE TABLE "
+ tableName + "(");
for (String cols : columnsDefs)
createDB.append(" " + cols + ",");
// 移除最后一个,号
String tableSQL = createDB.substring(0, createDB.length() - 1)
+ ");";
// 输出创建表的过程
System.out.println("Table Creation SQL is:\n" + tableSQL);
return tableSQL;
}
}
// 返回指定的约束
public String getConstraints(Constraints con) {
String constras = "";
if (!con.allowNull())
constras += " NOT NULL";
if (con.primaryKey())
constras += " PRIMARY KEY";
if (con.unique())
constras += " UNIQUE";
return constras;
}
}
Java注解annotation用法和自定义注解处理器的更多相关文章
- 深入理解Java的注解(Annotation):自定义注解入门(2)
要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其他注解.Java5. ...
- Annotation之三:自定义注解示例,利用反射进行解析
@Retention定义了该Annotation被保留的时间长短有3中RetentionPolicy.SOURCE源文件有效,RetentionPolicy.CLASS:在class文件中有效,Ret ...
- Java注解Annotation的用法 - 自定义Annotation实现
Java注解又称Java标注,是Java语言5.0版本开始支持加入源代码的特殊语法元数据. Java语言中的类.方法.变量.参数和包等都可以被标注.和Javadoc不同,Java标注可以通过反射获取标 ...
- [Java]利用拦截器和自定义注解做登录以及权限验证
1.自定义注解 需要验证登录的注解 package com.etaofinance.wap.common; import java.lang.annotation.Documented; import ...
- java中的注解详解和自定义注解
一.java中的注解详解 1.什么是注解 用一个词就可以描述注解,那就是元数据,即一种描述数据的数据.所以,可以说注解就是源代码的元数据.比如,下面这段代码: @Override public Str ...
- java之aop使用及自定义注解
目的: 1.Java注解简介 2.Java元注解(重点) 3.自定义注解 案例一(获取类与方法上的注解值) 案例二(获取类属性上的注解属性值) 案例三(获取参数修饰注解对应的属性值) 4.Aop自定义 ...
- java 编程基础:【注解】 提取注解信息,利用自定义注解编写测试类,注解绑定事件
提取注解信息 使用注解修饰了类.方法.成员变量等成员之后,这些注解不会自己生效,必须由开发者提供相应工具来提取并处理注解信息. Java使用java.lang.annotation.Annotat ...
- Java注解(Annotation)用法:利用注解和反射机制指定列名导出数据库数据
闲来没事,想了一个应用的例子:用java如何把数据库的数据根据我们指定的某几列,如第2列,第4列,第6列导出来到Excel里? 写代码也是为了应用的,写好的代码更重要的是在于思考.我自己思考了这个示例 ...
- Java注解【四、自定义注解】
语法要求.元注解 元注解: Target-适用范围: Retention-类型:源码注解.编译时注解.运行时注解 Inherited-可继承(只能继承类上的注解,接口.类中的方法都不行) Docume ...
- Spring实现自定义注解并且配置拦截器进行拦截
有时候我们会自定义注解,并且需要配置拦截器对请求方法含有该自定义注解的方法进行拦截操作 自定义注解类 NeedToken.java import java.lang.annotation.Docume ...
随机推荐
- 给网站添加Let's Encrypt的免费ssl证书
概要 目前很多浏览器默认都会标记http访问的网站为不安全,https部署已经称为大趋势,我之前利用业余时间搭建了一个网站,本文就以这个域名为基础说明如何给网站加上证书.本文使用的操作系统centos ...
- C语言:应用程序增加库函数rand的步骤
rand函数用来生成随机数,函数原型为int rand( void ); 返回值为生成的随机数,范围0~32767.在调用rand之前可以用srand函数初始化随机数发生器来生成更随机的数. 可以通过 ...
- docker 修改容器内容后更新镜像的流程
在 Docker 中,如果你修改了一个容器的内容并希望将这些更改保存为一个新的镜像,可以按照以下步骤进行: docker version: 26.1 1. 确保容器运行 首先,确保你正在修改的容器是运 ...
- 学习高校课程-软件设计模式-软件设计原则(lec2)
Feature of Good Design (1) 优秀设计的特点(一) Code reuse 代码复用 – Challenge: tight coupling between components ...
- 多表查询 —— 内连接&外连接&子查询
连接查询 内连接 1.查询语法 -- 隐式内连接 select 字段列表 from 表1, 表2... where 条件; -- 显式内连接 select 字段列表 from 表1 [INNER] j ...
- linux、unix软链接注意事项
前言 在使用linux过程中,经常使用到软链接(类似windows快捷方式): 创建软链接之后,删除时不注意就会出现到问题 先说结论 删除软链接,确实是使用rm进行删除:但是有个小细节必须要特别注意! ...
- vsphere8.0 VCenter部署
一.vCenter Server 介绍 vCenter Server是VMware提供的一种集中管理平台,用于管理和监控虚拟化环境中的虚拟机.主机.存储和网络等资源.它提供了一套功能强大的工具和界面, ...
- PHP中几种常见的开发模式
设计模式 单例模式 $_instance必须声明为静态的私有变量 构造函数和析构函数必须声明为私有,防止外部程序new 类从而失去单例模式的意义 getInstance()方法必须设置为公有的,必须 ...
- MySQL精品学习资源合集 | 含学习教程笔记、运维技巧、图书推荐
MySQL凭借开源.免费.低门槛.稳定等优势,成为了当前最流行的关系型数据库之一.从1998年发行第一版以来,通过不断地更新迭代,MySQL被越来越多的公司使用,已然成为当下潮流. 为了帮助大家更好地 ...
- 强大的无头UI表格库:TanStack Table!Github Star达到了惊人的25K!
强大的无头UI表格库:TanStack Table!Github Star达到了惊人的25K! 在构建现代化 Web 应用时,表格和数据网格是常见的 UI 组件,特别是在处理大量数据或需要复杂交互时, ...