知道美河 | 上传资料 | VIP申请 | 精品课程 | 资料搜索 | 问题反馈 | 会员手册 | 积分消费 | 积分充值 | 帐号保护
美河学习学习在线赞助VIP

美河学习在线(主站) eimhe.com

 找回密码
 建立账号
查看: 6332|回复: 5

[转帖] 学习教程:Java Annotation 高级应用

[复制链接]
发表于 2007-4-20 22:42:23 | 显示全部楼层 |阅读模式
 好东西 大家一起来共享

前言:

  前不久在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 telephone=null;
        
        //友人住址:家庭、单位
        @Persistent
        private ArrayList AddressForText=null;
        
        //备注
        @Persistent
        private String note=null;
        
        public AddressListForTest(String name,int age,
                        ArrayList telephoneList,
                        ArrayList addressList,
                        String note){
                this.friendName=name;
                this.age=age;
                this.telephone=new ArrayList(telephoneList);
                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

[ 本帖最后由 大灰狼挑灯品书 于 2007-4-20 22:48 编辑 ]
发表于 2007-4-20 23:16:57 | 显示全部楼层
大灰狼兄,你这个讲的是注释?
惭愧,学了这么久,只用用一般的注释,文档注释很少用
 楼主| 发表于 2007-4-20 23:26:01 | 显示全部楼层
呵呵
注释不一定只用在文档注释的
在EJB3.0中就特用大用注释
它就可以直接生产相对应的XML配置文件
甚至也可以写JAVA类文件

[ 本帖最后由 大灰狼挑灯品书 于 2007-4-20 23:27 编辑 ]
发表于 2007-4-20 23:39:54 | 显示全部楼层

回复 #3 大灰狼挑灯品书 的帖子

谢谢您的解释,我只用过EJB2.0,看来3.0的变化的确很大,对了,顺便问下,你的工作流的视频创作进展的如何了啊?虽然我现在只会使用SSH框架,但还是时刻关注着(工作流的概要含义又是啥?需要什么基础才可以进入这一阶段的学习 因为以前从没用过这方面的技术,希望能从你那里偷师)
 楼主| 发表于 2007-4-21 10:45:23 | 显示全部楼层
发表于 2007-4-22 08:48:12 | 显示全部楼层
您需要登录后才可以回帖 登录 | 建立账号

本版积分规则

 
QQ在线咨询

QQ|小黑屋|手机版|Archiver|美河学习在线 ( 浙网备33020302000026号 )

GMT+8, 2025-5-4 05:41

Powered by Discuz!

© 2001-2025 eimhe.com.

快速回复 返回顶部 返回列表