Java元注解的实战应用-实体类注解封装(下)
2017-08-04 14:21
330 查看
一)元注解简介
在java.lang.annotation包下,定义了6个元注解。元注解就是修饰注解的注解。拿到一个注解,如何知道它是否是元注解呢?需要看它的元注解(无论是元注解还是普通注解都是有元注解的),如果看到这样的元注解:@Target(ElementType.ANNOTATION_TYPE),那么此时这个注解一定是元注解。
@Retention
@Target
@Documented
@Inherited
@Repeatable (java 8新增)
类型注解
@Repetable和类型注解暂时不介绍
1.1 @Retention
@Retention用于指定注解可以保留多长时间(生命周期)。@Retention包含一个名为“value”的成员变量,该value成员变量是RetentionPolicy枚举类型。使用@Retention时,必须为其value指定值。value成员变量的值只能是如下3个:
RetentionPolicy.SOURCE:Annotation只保留在源代码中,编译器编译时,直接丢弃这种Annotation,不记录在.class文件中。
RetentionPolicy.CLASS:编译器把Annotation记录在class文件中。当运行Java程序时,JVM中不可获取该Annotation信息。这是默认值
RetentionPolicy.RUNTIME:编译器把Annotation记录在class文件中。当运行Java程序时,JVM可获取该Annotation信息,程序可以通过反射获取该Annotation的信息。
示例:
[java] view
plain copy
package com.demo1;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
//name=value形式
//@Retention(value=RetentionPolicy.RUNTIME)
//直接指定
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTag{
String name() default "我兰";
}
如果Annotation里有一个名为“value“的成员变量,使用该Annotation时,可以直接使用XXX(val)形式为value成员变量赋值,无须使用name=val形式。
1.2 @Target
@Target指定Annotation用于修饰哪些程序元素。@Target也包含一个名为”value“的成员变量,该value成员变量类型为ElementType[ ],ElementType为枚举类型,值有如下几个:ElementType.TYPE:能修饰类、接口或枚举类型
ElementType.FIELD:能修饰成员变量
ElementType.METHOD:能修饰方法
ElementType.PARAMETER:能修饰参数
ElementType.CONSTRUCTOR:能修饰构造器
ElementType.LOCAL_VARIABLE:能修饰局部变量
ElementType.ANNOTATION_TYPE:能修饰注解
ElementType.PACKAGE:能修饰包
示例1(单个ElementType):
[java] view
plain copy
package com.demo1;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
public @interface AnnTest {
String name() default "测试Target";
}
示例2(多个ElementType):
[java] view
plain copy
package com.demo1;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(<span style="color:#cc0000">{ ElementType.FIELD, ElementType.METHOD }</span>)
public @interface AnnTest {
String name() default "测试target!";
}
1.3 @Documented
如果定义注解A时,使用了@Documented修饰定义,则在用javadoc命令生成API文档后,所有使用注解A修饰的程序元素,将会包含注解A的说明。示例:
[java] view
plain copy
@Documented
public @interface Testable {
}
[java] view
plain copy
public class Test {
@Testable
public void info() {
}
}
1.4 @Inherited
@Inherited指定注解具有继承性。如果某个类使用了@xxx注解(定义该注解时使用了@Inherited修饰)修饰,则其子类将自动被@xxx修饰示例:
[java] view
plain copy
package com.demo2;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyTag{
}
[java] view
plain copy
package com.demo2;
@MyTag
public class Base {
}
[java] view
plain copy
package com.demo2;
//SubClass只是继承了Base类
//并未直接使用@MyTag注解修饰
public class SubClass extends Base {
public static void main(String[] args) {
System.out.println(SubClass.class.isAnnotationPresent(MyTag.class));
}
}
示例中Base使用@MyTag修饰,SubClass继承Base,而且没有直接使用@MyTag修饰,但是因为MyTag定义时,使用了@Inherited修饰,具有了继承性,所以运行结果为true。
如果MyTag注解没有被@Inherited修饰,则运行结果为:false。
二)元注解语法及定义形式
(1)以@interface关键字定义(2)注解需要标明注解的生命周期,注解的修饰目标等信息,这些信息是通过元注解实现。
上面的语法不容易理解,下面通过例子来说明一下,这个例子就是Target注解的源码,
1 2 3 4 5 6 | @Retention(value=RetentionPolicy.RUNTIME) @Target(value={ElementType.ANNOTATION_TYPE}) public@interfaceTarget { ElementType[]value(); } |
第一:元注解@Retention,成员value的值为RetentionPolicy.RUNTIME。
第二:元注解@Target,成员value是个数组,用{}形式赋值,值为ElementType.ANNOTATION_TYPE
第三:成员名称为value,类型为ElementType[]
另外,需要注意一下,如果成员名称是value,在赋值过程中可以简写。如果成员类型为数组,但是只赋值一个元素,则也可以简写。如上面的简写形式为:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
三)简单实例应用——实体类注解封装
1)主键id注解
package com.xiu.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
*
* @author xiu
* @version 2017年8月4日 上午11:17:05
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Id {
/**ID生成策略
* @return
*/
public Strategy strategy() default Strategy.IDENTITY;
/**ID序号
* @return
*/
public int sort() default 0;
public static enum Strategy{
/**
* 自定义ID
*/
IDENTITY,
/**
* 自增长ID
*/
AUTO
}
}
2)索引index注解
package com.xiu.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*数据库索引属性
*
* @author xiu
* @version 2017年8月4日 上午11:23:23
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Index {
/**
* 索引名字
* @return
*/
public String[] names() default {};
/**
* 索引引用的列名
* @return
*/
public String[] indexs() default {};
/**
* 索引的类型
* @return
*/
public Type[] types() default {};
/**
* 索引的方式
* @return
*/
public Way[] ways() default {};
public static enum Type {
NORMAL(""),//普通
UNIQUE("UNIQUE"),//唯一
FULLTEXT("FULLTEXT");//全参数
private String value;
private Type(String value){
this.value = value;
}
public String value() {
return this.value;
}
}
public static enum Way {
BTREE("BTREE"),//tree方式
HASH("HASH");//hash方式
private String value;
private Way(String value) {
this.value = value;
}
public String value() {
return this.value;
}
}
}
3)注释column
package com.xiu.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** *表字段注解 * @author xiu * @version 2017年8月4日 上午11:13:09 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Column { /**字段长度,仅对String生效 * @return */ public int length() default 255; /**备注 * @return */ public String comment(); }
4)父类MappedSuperclass注解
package com.xiu.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** *父类注解 * * @author xiu * @version 2017年8月4日 上午11:42:21 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface MappedSuperclass { }
5)@Transient注解
package com.xiu.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** *非持久化属性 * * @author xiu * @version 2017年8月4日 上午11:48:50 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Transient { }
6)表名@Table
package com.xiu.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*数据库表的属性
*
* @author xiu
* @version 2017年8月4日 上午11:45:17
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Table {
/**
* 表名
* @return
*/
public String name() default "";
/**
* 分表数
* @return
*/
public int catalog() default 0;
/**
* 结合catalog的组合定义
* 例如catalog = 10,catalog_ = 0,分表数为0到9
* 例如catalog = 6,catalog_ = 1,分表数为1到5
*
* @return
*/
public int catalog_() default 0;
/**
* 分表根据字段
* @return
*/
public String catalogby() default "";
/**
* 表注释
* @return
*/
public String comment() default "";
}
7)使用方式
这种实体类相关注解的使用在实际开发中非常频繁,封装起来的数据库实体注解特别在服务端游戏开发中应用更为广泛。
package com.xiu.annotation.entity;
import java.io.Serializable;
import java.util.List;
import com.xiu.annotation.Column;
import com.xiu.annotation.Id;
import com.xiu.annotation.Id.Strategy;
import com.xiu.annotation.Index;
import com.xiu.annotation.Table;
import com.xiu.annotation.Transient;
/**
*游戏战斗道具实体类
*
* @author xiu
* @version 2017年8月4日 上午11:55:03
*/
@Table(name = "game_battle_item", comment = "游戏战斗道具")
@Index(names = {"rid"}, indexs = {"rid"})
public class Item implements Serializable {
private static final long serialVersionUID = 4496679862865864947L;
@Id(strategy=Strategy.AUTO)
@Column(comment = "id")
private long id;
@Column(comment = "玩家id")
private long rid;
@Column(comment = "道具id")
private int itemId;
@Column(comment = "道具数量")
private int num;
//不持久化的临时数据
@Transient
private List<Integer> itemIdList;
//getter、setter
}
相关文章推荐
- JAVA源码分享:基于Apache POI,将List<T>内封装的实体类信息写出到磁盘Excel文件
- 读《轻量级Java_EE企业应用实战》与关于JavaBean
- java注解应用实例 - Annotation, 自定义注解, 注解类规则
- java注解应用实例 - Annotation, 自定义注解, 注解类规则
- 自定义Java注解的方式与应用
- 深入理解Java注解(2):高级应用
- Java注解学习和应用
- Deeplearning4j 实战(3):简介Nd4j中JavaCPP技术的应用
- Java培训实战教程之Java基础知识精华部分(四)-封装
- linux中级-JAVA企业级应用TOMCAT实战
- JAVA企业级应用TOMCAT实战
- 黑马程序员之Java--了解注解及其应用
- [JAVA] JDK5.0 Annotations注解hibernate实体类
- Java模块 -- Java注解及应用
- java基本类型和封装类型区别及应用
- Java 注解的简单学习与应用 Annotation
- Java 8 可重复注解的理解与应用
- 实体类注解错误:Could not determine type for: java.util.Set
- java自定义注解学习(三)_注解解析及应用
- 求助!精通Spring 4.x 企业应用开发实战;第二章;测试过程报java.lang.IllegalStateException: Failed to load ApplicationContext