前言:
前不久在matrix上先后发表了《java annotation 入门》、《java annotation 手册》两篇文章,比较全面的对java annotation的语法、原理、使用三方面进行了阐述。由于《入门》中的简单例程虽然简单明了的说明了annotation用法,但给大家的感觉可能是意犹未见,所以在此行文《java annotation高级应用》,具体实例化解释annotation和annotation processing tool(apt)的使用。望能对各位的有所帮助。
一、摘要:
《java annotation高级应用》具体实例化解释annotation和annotation processing tool(apt)的使用。望能对各位的有所帮助。本文列举了用于演示annotation的brfw演示框架、演示apt的apt代码实例,并对其进行较为深度的分析,希望大家多多提意见。
二、annotation实例分析
1.brfw(beaninfo runtime framework)定义:
本人编写的一个annotation功能演示框架。顾名思义,brfw就是在运行时取得bean信息的框架。
2.brfw的功能:
a.源代码级annotation:在bean的源代码中使用annotation定义bean的信息;
b.运行时获取bean数据:在运行时分析bean class中的annotation,并将当前bean class中field信息取出,功能类似xdoclet;
c.运行时bean数据的xml绑定:将获得的bean数据构造为xml文件格式展现。熟悉j2ee的朋友知道,这个功能类似jaxb.
3.brfw框架:
brfw主要包含以下几个类:
a.persistent类:定义了用于修饰类的固有类型成员变量的annotation.
b.exportable类:定义了用于修饰class的类型的annotation.
c.exporttoxml类:核心类,用于完成brfw的主要功能:将具有exportable annotation的bean对象转换为xml格式文本。
d.addressfortest类:被a和b修饰过的用于测试目的的地址bean类。其中包含了地址定义所必需的信息:国家、省级、城市、街道、门牌等。
e.addresslistfortest类:被a和b修饰过的友人通讯录bean类。其中包含了通讯录所必备的信息:友人姓名、年龄、电话、住址(成员为addressfortest类型的arraylist)、备注。需要说明的是电话这个bean成员变量是由字符串类型组成的arraylist类型。由于朋友的住址可能不唯一,故这里的住址为由addressfortest类型组成的arraylist.
从上面的列表中,可以发现a、b用于修饰bean类和其类成员;c主要用于取出bean类的数据并将其作xml绑定,代码中使用了e作为测试类;e中可能包含着多个d.
在了解了这个简单框架后,我们来看一下brfw的代码吧!
4.brfw源代码分析:
a.persistent类:
清单1:
package com.bjinfotech.practice.annotation.runtimeframework;
import java.lang.annotation.*;
/**
* 用于修饰类的固有类型成员变量的annotation
* @author cleverpig
*
*/
@retention(retentionpolicy.runtime)
@target(elementtype.field)
public @interface persistent {
string value() default "";
}
b.exportable类:
清单2:
package com.bjinfotech.practice.annotation.runtimeframework;
import java.lang.annotation.*;
/**
* 用于修饰类的类型的annotation
* @author cleverpig
*
*/
@retention(retentionpolicy.runtime)
@target(elementtype.type)
public @interface exportable {
//名称
string name() default "";
//描述
string description() default "";
//省略name和description后,用来保存name值
string value() default "";
}
c.addressfortest类:
清单3:
package com.bjinfotech.practice.annotation.runtimeframework;
/**
* 用于测试的地址类
* @author cleverpig
*
*/
@exportable("address")
public class addressfortest {
//国家
@persistent
private string country=null;
//省级
@persistent
private string province=null;
//城市
@persistent
private string city=null;
//街道
@persistent
private string street=null;
//门牌
@persistent
private string doorplate=null;
public addressfortest(string country,string province,
string city,string street,string doorplate){
this.country=country;
this.province=province;
this.city=city;
this.street=street;
this.doorplate=doorplate;
}
}
d.addresslistfortest类:
清单4:
package com.bjinfotech.practice.annotation.runtimeframework;
import java.util.*;
/**
* 友人通讯录
* 包含:姓名、年龄、电话、住址(多个)、备注
* @author cleverpig
*
*/
@exportable(name="addresslist",description="address list")
public class addresslistfortest {
//友人姓名
@persistent
private string friendname=null;
//友人年龄
@persistent
private int age=0;
//友人电话
@persistent
private arraylist
//友人住址:家庭、单位
@persistent
private arraylist addressfortext=null;
//备注
@persistent
private string note=null;
public addresslistfortest(string name,int age,
arraylist
arraylist addresslist,
string note){
this.friendname=name;
this.age=age;
this.telephone=new arraylist
this.addressfortext=new arraylist(addresslist);
this.note=note;
}
}
e.exporttoxml类:
清单5:
package com.bjinfotech.practice.annotation.runtimeframework;
import java.lang.reflect.field;
import java.util.collection;
import java.util.iterator;
import java.util.map;
import java.util.arraylist;
/**
* 将具有exportable annotation的对象转换为xml格式文本
* @author cleverpig
*
*/
public class exporttoxml {
/**
* 返回对象的成员变量的值(字符串类型)
* @param field 对象的成员变量
* @param fieldtypeclass 对象的类型
* @param obj 对象
* @return 对象的成员变量的值(字符串类型)
*/
private string getfieldvalue(field field,class fieldtypeclass,object obj){
string value=null;
try{
if (fieldtypeclass==string.class){
value=(string)field.get(obj);
}
else if (fieldtypeclass==int.class){
value=integer.tostring(field.getint(obj));
}
else if (fieldtypeclass==long.class){
value=long.tostring(field.getlong(obj));
}
else if (fieldtypeclass==short.class){
value=short.tostring(field.getshort(obj));
}
else if (fieldtypeclass==float.class){
value=float.tostring(field.getfloat(obj));
}
else if (fieldtypeclass==double.class){
value=double.tostring(field.getdouble(obj));
}
else if (fieldtypeclass==byte.class){
value=byte.tostring(field.getbyte(obj));
}
else if (fieldtypeclass==char.class){
value=character.tostring(field.getchar(obj));
}
else if (fieldtypeclass==boolean.class){
value=boolean.tostring(field.getboolean(obj));
}
}
catch(exception ex){
ex.printstacktrace();
value=null;
}
return value;
}
/**
* 输出对象的字段,当对象的字段为collection或者map类型时,要调用exportobject方法继续处理
* @param obj 被处理的对象
* @throws exception
*/
public void exportfields(object obj) throws exception{
exportable exportable=obj.getclass().getannotation(exportable.class);
if (exportable!=null){
if (exportable.value().length()>0){
// system.out.println("class annotation name:"+exportable.value());
}
else{
// system.out.println("class annotation name:"+exportable.name());
}
}
else{
// system.out.println(obj.getclass()+"类不是使用exportable标注过的");
}
//取出对象的成员变量
field[] fields=obj.getclass().getdeclaredfields();
for(field field:fields){
//获得成员变量的标注
persistent fieldannotation=field.getannotation(persistent.class);
if (fieldannotation==null){
continue;
}
//重要:避免java虚拟机检查对私有成员的访问权限
field.setaccessible(true);
class typeclass=field.gettype();
string name=field.getname();
string value=getfieldvalue(field,typeclass,obj);
//如果获得成员变量的值,则输出
if (value!=null){
system.out.println(getindent()+"<"+name+">/n"
+getindent()+"/t"+value+"/n"+getindent()+"");
}
//处理成员变量中类型为collection或map
else if ((field.get(obj) instanceof collection)||
(field.get(obj) instanceof map)){
exportobject(field.get(obj));
}
else{
exportobject(field.get(obj));
}
}
}
//缩进深度
int leveldepth=0;
//防止循环引用的检查者,循环引用现象如:a包含b,而b又包含a
collectioncyclicchecker=new arraylist
新闻热点
疑难解答
图片精选