Java注解(2)-注解处理器(运行时|RetentionPolicy.RUNTIME)
来源:互联网 发布:投票软件免费下载 编辑:程序博客网 时间:2024/06/06 05:43
如果没有用来读取注解的工具,那注解将基本没有任何作用,它也不会比注释更有用。读取注解的工具叫作注解处理器。Java提供了两种方式来处理注解:第一种是利用运行时反射机制;另一种是使用Java提供的API来处理编译期的注解。
反射机制方式的注解处理器
仅当定义的注解的@Retention为RUNTIME时,才能够通过运行时的反射机制来处理注解。下面结合例子来说明这种方式的处理方法。
Java中的反射API(如java.lang.Class、java.lang.reflect.Field等)都实现了接口java.lang.reflect.AnnotatedElement,来提供获取类、方法和域上的注解的实用方法。
通过JavaBean上定义的注解来生成相应的SQL。
1.1、定义注解
1.1.1、类注解映射表名
package
com.zenfery.example.annotation.sql;
import
java.lang.annotation.ElementType;
import
java.lang.annotation.Retention;
import
java.lang.annotation.RetentionPolicy;
import
java.lang.annotation.Target;
@Target
(ElementType.TYPE)
//定义注解应用于类
@Retention
(RetentionPolicy.RUNTIME)
//定义注解在JVM运行时保留
public
@interface
TableSQL {
String value()
default
""
;
//指定对应的表名
}
定义注解@TableSQL,只定义一个value值来映射表名,默认值为空,如果程序不给此值,将使用类名(小写)来作为表名。
1.1.2、属性与字段对应注解
package
com.zenfery.example.annotation.sql;
import
java.lang.annotation.ElementType;
import
java.lang.annotation.Retention;
import
java.lang.annotation.RetentionPolicy;
import
java.lang.annotation.Target;
@Target
(<span style=
"color: #0000ff;"
>ElementType.FIELD</span>)
//定义注解应用于成员变量
@Retention
(RetentionPolicy.RUNTIME)
//定义注解在JVM运行时保留
public
@interface
TableColumnSQL {
String value()
default
""
;
Constraint constraint()
default
@Constraint
();
}
定义注解@TableColumnSQL的目标为FIELD,仅能在类的属性上使用;value()属性定义对应的字段名;constraint()定义字段的约束,它是由注解@Constraint定义,其定义如下:
package
com.zenfery.example.annotation.sql;
import
java.lang.annotation.ElementType;
import
java.lang.annotation.Retention;
import
java.lang.annotation.RetentionPolicy;
import
java.lang.annotation.Target;
@Target
(<span style=
"color: #0000ff;"
>ElementType.FIELD</span>)
//定义注解应用于成员变量
@Retention
(RetentionPolicy.RUNTIME)
//定义注解在JVM运行时保留
public
@interface
Constraint {
boolean
allowNull()
default
true
;
//是否允许为空
boolean
isPrimary()
default
false
;
//是否为主键
}
@Constraint注解仅定义了两个注解元素,allowNull()指定字段是否允许为空值;isPrimary()指定字段是否是主键。
1.2、定义JavaBean
package
com.zenfery.example.annotation.clazz;
import
com.zenfery.example.annotation.sql.Constraint;
import
com.zenfery.example.annotation.sql.TableColumnSQL;
import
com.zenfery.example.annotation.sql.TableSQL;
/**
* 定义User类与数据库映射
* @author zenfery
*/
@TableSQL
()
public
class
User {
//定义id字段,与表user的列id相映射,指定约束为:不为空,为主键。
@TableColumnSQL
(value=
"id"
,constraint=
@Constraint
(allowNull=
false
,isPrimary=
true
))
String id;
//只为注解指定value字段,可省略value。
@TableColumnSQL
(
"name"
)
String name;
}
定义User类。类上使用@TableSQL来注解映射表名;字段id和name使用@TableColumnSQL来注解映射字段名。
1.2、注解处理器
在以上工作做完后,注解没有任何意义(它没有做任何事情),下面来为RUNTIME级别的注解来编写处理器,在此编写的处理器和真实的处理器相差比较多,无通用性,仅为演示理解用。详细代码如下:
package
com.zenfery.example.annotation.clazz;
import
java.lang.annotation.Annotation;
import
java.lang.reflect.Field;
import
java.util.ArrayList;
import
java.util.List;
import
com.zenfery.example.annotation.sql.Constraint;
import
com.zenfery.example.annotation.sql.TableColumnSQL;
import
com.zenfery.example.annotation.sql.TableSQL;
public
class
TableSQLHandler {
/**
* 注解处理器:读取User类中注解,生成对应的SQL并打印出来
* 在此假设表的所有字段均为varchar(10)
* @since JDK 1.6
* @param args
*/
public
static
void
main(String[] args) {
/**
* 注解的@Retention均为JVM保留注解(RetentionPolicy.RUNTIME)
* ,在此直接使用main方法启动JVM,通过Java提供的反射机制来处
* 理。
*/
try
{
//指定在JVM需要处理注解的类
Class userClass =
null
;
//userClass = Class.forName("com.zenfery.example.annotation.clazz.User");
userClass = User.
class
;
//打印所有类的注解
Annotation[] annotations = userClass.getDeclaredAnnotations();
for
(
int
i=
0
; i<annotations.length; i++){
System.out.println(
"注解["
+(i+
1
)+
"] = "
+annotations[i].toString());
}
//检查类是否有@TableSQL注解
if
( userClass.isAnnotationPresent(TableSQL.
class
) ){
//sql
String sql =
"\nCREATE TABLE "
;
//注解了TableSQL注解
TableSQL ts = (TableSQL)userClass.getAnnotation(TableSQL.
class
);
String tableName = ts.value();
if
(
""
.equals(tableName)){
//如果获取的值为TableSQL的默认值,则使用类名来做为表名
tableName = userClass.getSimpleName().toLowerCase();
}
System.out.println(
"获取"
+userClass.getName()+
"对应的表名为:"
+tableName);
sql += tableName +
" ( \n"
;
//从User类的属性中获取需要与数据库映射的字段
Field[] fields = userClass.getDeclaredFields();
List<String> primaryKeys =
new
ArrayList<String>();
//存储主键
for
(
int
i=
0
; i<fields.length; i++){
Field field = fields[i];
if
( field.isAnnotationPresent(TableColumnSQL.
class
) ){
TableColumnSQL tcs = (TableColumnSQL)field.getAnnotation(TableColumnSQL.
class
);
String fieldName = tcs.value();
//表中的字段名
Constraint c = tcs.constraint();
//字段对应的约束
boolean
allowNull = c.allowNull();
//是否可为空
boolean
isPrimary = c.isPrimary();
//是否为主键
//拼接SQL
sql +=
"\t"
+ fieldName +
" VARCHAR(10)"
;
if
(!allowNull) sql +=
" NOT NULL"
;
//不允许为空
if
(i<fields.length-
1
) sql+=
",\n"
;
//主键
if
(isPrimary) primaryKeys.add(fieldName);
}
else
{
System.out.println(
"字段"
+field.getName()+
"未使用注解@TableColumnSQL!"
);
}
}
if
(primaryKeys.size()>
0
){
StringBuilder keys =
new
StringBuilder();
for
(
int
k=
0
; k<primaryKeys.size(); k++){
keys.append(primaryKeys.get(k));
if
(k<primaryKeys.size()-
1
)keys.append(
","
);
}
sql +=
",\n\tPRIMARY KEY "
+keys.toString();
}
sql +=
"\n) DEFAULT CHARSET=utf8"
;
// ====> 打印SQL
System.out.println(
"生成的SQL:"
+sql);
}
else
{
System.out.println(
"警告:"
+userClass.getName()+
"未使用@TableSQL注解!"
);
}
}
catch
(Exception e) {
e.printStackTrace();
}
}
}
- 获取使用了注解的User类。
- 根据类上的注解@TableSQL获取表名。
- 根据类中所有的字段上的注解@TableColumnSQL来获取字段名,并获取字段的特性。
- 根据获取的表名和字段名拼接SQL。
- 打印SQL。
运行TableSQLHandler的main()方法,输出:
注解[1] = @com.zenfery.example.annotation.sql.TableSQL(value=)
获取com.zenfery.example.annotation.clazz.User对应的表名为:user
生成的SQL:
CREATE TABLE user (
id VARCHAR(10) NOT NULL,
name VARCHAR(10),
PRIMARY KEY id
) DEFAULT CHARSET=utf8
转载请注明:子暃之路 » Java注解(2)-注解处理器(运行时|RetentionPolicy.RUNTIME)
- Java注解(2)-注解处理器(运行时|RetentionPolicy.RUNTIME)
- 自定义注解之运行时注解(RetentionPolicy.RUNTIME)
- 自定义注解之运行时注解(RetentionPolicy.RUNTIME)
- Java注解-注解处理器(编译期|RetentionPolicy.SOURCE)
- Java注解(3)-注解处理器(编译期|RetentionPolicy.SOURCE)
- Java注解(2)-自定义注解、注解处理器
- Java注解处理器(编译时注解)
- 注解之RetentionPolicy,ElementType
- 注解之RetentionPolicy,ElementType
- Java注解(二):注解处理器
- java注解处理器(运行时和编译时处理的注解)
- 自定义注解之编译时注解(RetentionPolicy.CLASS)(一)
- 自定义注解之编译时注解(RetentionPolicy.CLASS)(一)
- java 注解:注解(Annotation)--注解处理器
- Java注解处理器
- Java注解处理器
- Java 注解处理器
- Java注解处理器
- Linux 动态库的使用
- as连接不上手机
- Repeater中使用Button
- SQLDB 相关书籍
- Java中的ReentrantLock和synchronized两种锁定机制的对比
- Java注解(2)-注解处理器(运行时|RetentionPolicy.RUNTIME)
- android.intent.action大全
- 根据一只猿前辈的TPLINK和海康威视漏扫工具改进的IPscanner成果展示(20170314 更新)
- 用touch创建新文件
- 微信小程序完整开发过程
- VM虚拟机上安装Ubuntu16.04的phplamp环境
- 二分查找之美:二分查找及其变体的正确性以及构造方式
- 调起百度、高德、腾讯地图导航功能
- maven的setting配置文件