package com.bjinfotech.practice.annotation.runtimeframework;
import java.lang.annotation.*;
/**
* 用于修飾類(lèi)的固有類(lèi)型成員變量的annotation
* @author cleverpig
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Persistent {
String value() default "";
}
package com.bjinfotech.practice.annotation.runtimeframework;
import java.lang.annotation.*;
/**
* 用于修飾類(lèi)的類(lèi)型的annotation
* @author cleverpig
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Exportable {
//名稱(chēng)
String name() default "";
//描述
String description() default "";
//省略name和description后,用來(lái)保存name值
String value() default "";
}
package com.bjinfotech.practice.annotation.runtimeframework;
/**
* 用于測(cè)試的地址類(lèi)
* @author cleverpig
*
*/
@Exportable("address")
public class AddressForTest {
//國(guó)家
@Persistent
private String country=null;
//省級(jí)
@Persistent
private String province=null;
//城市
@Persistent
private String city=null;
//街道
@Persistent
private String street=null;
//門(mén)牌
@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;
}
}
package com.bjinfotech.practice.annotation.runtimeframework;
import java.util.*;
/**
* 友人通訊錄
* 包含:姓名、年齡、電話(huà)、住址(多個(gè))、備注
* @author cleverpig
*
*/
@Exportable(name="addresslist",description="address list")
public class AddressListForTest {
//友人姓名
@Persistent
private String friendName=null;
//友人年齡
@Persistent
private int age=0;
//友人電話(huà)
@Persistent
private ArrayList<String> telephone=null;
//友人住址:家庭、單位
@Persistent
private ArrayList<AddressForTest> AddressForText=null;
//備注
@Persistent
private String note=null;
public AddressListForTest(String name,int age,
ArrayList<String> telephoneList,
ArrayList<AddressForTest> addressList,
String note){
this.friendName=name;
this.age=age;
this.telephone=new ArrayList<String>(telephoneList);
this.AddressForText=new ArrayList<AddressForTest>(addressList);
this.note=note;
}
}
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的對(duì)象轉(zhuǎn)換為xml格式文本
* @author cleverpig
*
*/
public class ExportToXml {
/**
* 返回對(duì)象的成員變量的值(字符串類(lèi)型)
* @param field 對(duì)象的成員變量
* @param fieldTypeClass 對(duì)象的類(lèi)型
* @param obj 對(duì)象
* @return 對(duì)象的成員變量的值(字符串類(lèi)型)
*/
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;
}
/**
* 輸出對(duì)象的字段,當(dāng)對(duì)象的字段為Collection或者M(jìn)ap類(lèi)型時(shí),要調(diào)用exportObject方法繼續(xù)處理
* @param obj 被處理的對(duì)象
* @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()+"類(lèi)不是使用Exportable標(biāo)注過(guò)的");
}
//取出對(duì)象的成員變量
Field[] fields=obj.getClass().getDeclaredFields();
for(Field field:fields){
//獲得成員變量的標(biāo)注
Persistent fieldAnnotation=field.getAnnotation(Persistent.class);
if (fieldAnnotation==null){
continue;
}
//重要:避免java虛擬機(jī)檢查對(duì)私有成員的訪(fǎng)問(wèn)權(quán)限
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()+"</"+name+">");
}
//處理成員變量中類(lèi)型為Collection或Map
else if ((field.get(obj) instanceof Collection)||
(field.get(obj) instanceof Map)){
exportObject(field.get(obj));
}
else{
exportObject(field.get(obj));
}
}
}
//縮進(jìn)深度
int levelDepth=0;
//防止循環(huán)引用的檢查者,循環(huán)引用現(xiàn)象如:a包含b,而b又包含a
Collection<Object> cyclicChecker=new ArrayList<Object>();
/**
* 返回縮進(jìn)字符串
* @return
*/
private String getIndent(){
String s="";
for(int i=0;i<levelDepth;i++){
s+="\t";
}
return s;
}
/**
* 輸出對(duì)象,如果對(duì)象類(lèi)型為Collection和Map類(lèi)型,則需要遞歸調(diào)用exportObject進(jìn)行處理
* @param obj
* @throws Exception
*/
public void exportObject(Object obj) throws Exception{
Exportable exportable=null;
String elementName=null;
//循環(huán)引用現(xiàn)象處理
if (cyclicChecker.contains(obj)){
return;
}
cyclicChecker.add(obj);
//首先處理Collection和Map類(lèi)型
if (obj instanceof Collection){
for(Iterator i=((Collection)obj).iterator();i.hasNext();){
exportObject(i.next());
}
}
else if (obj instanceof Map){
for(Iterator i=((Map)obj).keySet().iterator();i.hasNext();){
exportObject(i.next());
}
}
else{
exportable=obj.getClass().getAnnotation(Exportable.class);
//如果obj已經(jīng)被Exportable Annotation修飾過(guò)了(注意annotation是具有繼承性的),
//則使用其name作為輸出xml的元素name
if (exportable!=null){
if (exportable.value().length()>0){
elementName=exportable.value();
}
else{
elementName=exportable.name();
}
}
//未被修飾或者Exportable Annotation的值為空字符串,
//則使用類(lèi)名作為輸出xml的元素name
if (exportable==null||elementName.length()==0){
elementName=obj.getClass().getSimpleName();
}
//輸出xml元素頭
System.out.println(getIndent()+"<"+elementName+">");
levelDepth++;
//如果沒(méi)有被修飾,則直接輸出其toString()作為元素值
if (exportable==null){
System.out.println(getIndent()+obj.toString());
}
//否則將對(duì)象的成員變量導(dǎo)出為xml
else{
exportFields(obj);
}
levelDepth--;
//輸出xml元素結(jié)尾
System.out.println(getIndent()+"</"+elementName+">");
}
cyclicChecker.remove(obj);
}
public static void main(String[] argv){
try{
AddressForTest ad=new AddressForTest("China","Beijing",
"Beijing","winnerStreet","10");
ExportToXml test=new ExportToXml();
ArrayList<String> telephoneList=new ArrayList<String>();
telephoneList.add("66608888");
telephoneList.add("66608889");
ArrayList<AddressForTest> adList=new ArrayList<AddressForTest>();
adList.add(ad);
AddressListForTest adl=new AddressListForTest("coolBoy",
18,telephoneList,adList,"some words");
test.exportObject(adl);
}
catch(Exception ex){
ex.printStackTrace();
}
}
}
<addresslist>
<friendName>
coolBoy
</friendName>
<age>
18
</age>
<String>
66608888
</String>
<String>
66608889
</String>
<address>
<country>
China
</country>
<province>
Beijing
</province>
<city>
Beijing
</city>
<street>
winnerStreet
</street>
<doorplate>
10
</doorplate>
</address>
<note>
some words
</note>
</addresslist>
package com.bjinfotech.practice.annotation.apt;
/**
* 定義Review Annotation
* @author cleverpig
*
*/
public @interface Review {
public static enum TypeEnum{EXCELLENT,NICE,NORMAL,BAD};
TypeEnum type();
String name() default "Review";
}
package com.bjinfotech.practice.annotation.apt;
import java.util.Collection;
import java.util.Set;
import java.util.Arrays;
import com.sun.mirror.apt.*;
import com.sun.mirror.declaration.AnnotationTypeDeclaration;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
//請(qǐng)注意為了方便,使用了靜態(tài)import
import static java.util.Collections.unmodifiableCollection;
import static java.util.Collections.emptySet;
/**
* 生成ReviewProcessor的工廠類(lèi)
* @author cleverpig
*
*/
public class ReviewProcessorFactory implements AnnotationProcessorFactory{
/**
* 獲得針對(duì)某個(gè)(些)類(lèi)型聲明定義的Processor
* @param atds 類(lèi)型聲明集合
* @param env processor環(huán)境
*/
public AnnotationProcessor getProcessorFor(
Set<AnnotationTypeDeclaration> atds,
AnnotationProcessorEnvironment env){
return new ReviewProcessor(env);
}
/**
* 定義processor所支持的annotation類(lèi)型
* @return processor所支持的annotation類(lèi)型的集合
*/
public Collection<String> supportedAnnotationTypes(){
//“*”表示支持所有的annotation類(lèi)型
//當(dāng)然也可以修改為“foo.bar.*”、“foo.bar.Baz”,來(lái)對(duì)所支持的類(lèi)型進(jìn)行修飾
return unmodifiableCollection(Arrays.asList("*"));
}
/**
* 定義processor支持的選項(xiàng)
* @return processor支持選項(xiàng)的集合
*/
public Collection<String> supportedOptions(){
//返回空集合
return emptySet();
}
public static void main(String[] argv){
System.out.println("ok");
}
}
package com.bjinfotech.practice.annotation.apt;
import com.sun.mirror.apt.AnnotationProcessor;
import com.sun.mirror.apt.AnnotationProcessorEnvironment;
import com.sun.mirror.declaration.TypeDeclaration;
import com.sun.mirror.util.DeclarationVisitors;
import com.sun.mirror.util.DeclarationVisitor;
/**
* 定義Review annotation的Processor
* @author cleverpig
*
*/
public class ReviewProcessor implements AnnotationProcessor{
//Processor所工作的環(huán)境
AnnotationProcessorEnvironment env=null;
/**
* 構(gòu)造方法
* @param env 傳入processor環(huán)境
*/
public ReviewProcessor(AnnotationProcessorEnvironment env){
this.env=env;
}
/**
* 處理方法:查詢(xún)processor環(huán)境中的類(lèi)型聲明,
*/
public void process(){
//查詢(xún)processor環(huán)境中的類(lèi)型聲明
for(TypeDeclaration type:env.getSpecifiedTypeDeclarations()){
//返回對(duì)類(lèi)進(jìn)行掃描、訪(fǎng)問(wèn)其聲明時(shí)使用的DeclarationVisitor,
//傳入?yún)?shù):new ReviewDeclarationVisitor(),為掃描開(kāi)始前進(jìn)行的對(duì)類(lèi)聲明的處理
// DeclarationVisitors.NO_OP,表示在掃描完成時(shí)進(jìn)行的對(duì)類(lèi)聲明不做任何處理
DeclarationVisitor visitor=DeclarationVisitors.getDeclarationScanner(
new ReviewDeclarationVisitor(),DeclarationVisitors.NO_OP);
//應(yīng)用DeclarationVisitor到類(lèi)型
type.accept(visitor);
}
}
}
package com.bjinfotech.practice.annotation.apt;
import com.sun.mirror.util.*;
import com.sun.mirror.declaration.*;
/**
* 定義Review annotation聲明訪(fǎng)問(wèn)者
* @author cleverpig
*
*/
public class ReviewDeclarationVisitor extends SimpleDeclarationVisitor{
/**
* 定義訪(fǎng)問(wèn)類(lèi)聲明的方法:打印類(lèi)聲明的全名
* @param cd 類(lèi)聲明對(duì)象
*/
public void visitClassDeclaration(ClassDeclaration cd){
System.out.println("獲取Class聲明:"+cd.getQualifiedName());
}
public void visitAnnotationTypeDeclaration(AnnotationTypeDeclaration atd){
System.out.println("獲取Annotation類(lèi)型聲明:"+atd.getSimpleName());
}
public void visitAnnotationTypeElementDeclaration(AnnotationTypeElementDeclaration aed){
System.out.println("獲取Annotation類(lèi)型元素聲明:"+aed.getSimpleName());
}
}
E:
rem 項(xiàng)目根目錄
set PROJECT_ROOT=E:\eclipse3.1RC3\workspace\tigerFeaturePractice
rem 包目錄路徑
set PACKAGEPATH=com\bjinfotech\practice\annotation\apt
rem 運(yùn)行根路徑
set RUN_ROOT=%PROJECT_ROOT%\build
rem 源文件所在目錄路徑
set SRC_ROOT=%PROJECT_ROOT%\test
rem 設(shè)置Classpath
set CLASSPATH=.;%JAVA_HOME%;%JAVA_HOME%/lib/tools.jar;%RUN_ROOT%
cd %SRC_ROOT%\%PACKAGEPATH%
apt -nocompile -factory com.bjinfotech.practice.annotation.apt.ReviewProcessorFactory ./*.java
聯(lián)系客服