Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 319|回复: 0

[注解学习]Annotation实例分析

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-28 23:56:39 | 显示全部楼层 |阅读模式
    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文件格式展现。

    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类:
    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 "";
    }[/code] B.Exportable类:
    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 "";
            
    }[/code] C.AddressForTest类:
    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;
            }
            
    }[/code] D.AddressListForTest类:
    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<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;
                   
            }
    }[/code] E.ExportToXml类:
    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+">
    "
                                                    +getIndent()+"        "+value+"
    "+getIndent()+"</"+name+">");
                            }
                            //处理成员变量中类型为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
            Collection<Object> cyclicChecker=new ArrayList<Object>();
            
            /**
             * 返回缩进字符串
             * @return
             */
            private String getIndent(){
                    String s="";
                    for(int i=0;i<levelDepth;i++){
                            s+="        ";
                    }
                    return s;
            }


            /**
             * 输出对象,如果对象类型为Collection和Map类型,则需要递归调用exportObject进行处理
             * @param obj
             * @throws Exception
             */
            public void exportObject(Object obj) throws Exception{
                    Exportable exportable=null;
                    String elementName=null;
                   
                    //循环引用现象处理
                    if (cyclicChecker.contains(obj)){
                            return;
                    }
                   
                    cyclicChecker.add(obj);
                   
                    //首先处理Collection和Map类型
                    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已经被Exportable Annotation修饰过了(注意annotation是具有继承性的),
                            //则使用其name作为输出xml的元素name
                            if (exportable!=null){
                                    if (exportable.value().length()>0){
                                            elementName=exportable.value();
                                    }
                                    else{
                                            elementName=exportable.name();
                                    }
                            }
                            //未被修饰或者Exportable Annotation的值为空字符串,
                            //则使用类名作为输出xml的元素name
                            if (exportable==null||elementName.length()==0){
                                    elementName=obj.getClass().getSimpleName();
                            }
                            //输出xml元素头
                            System.out.println(getIndent()+"<"+elementName+">");
                            levelDepth++;
                            //如果没有被修饰,则直接输出其toString()作为元素值
                            if (exportable==null){
                                    System.out.println(getIndent()+obj.toString());
                            }
                            //否则将对象的成员变量导出为xml
                            else{
                                    exportFields(obj);
                            }
                            levelDepth--;
                            //输出xml元素结尾
                            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();
                    }
            }
    }[/code]     在ExportToXml类之前的类比较简单,这里必须说明一下ExportToXml类:此类的核心函数是exportObject和exportFields方法,前者输出对象的xml信息,后者输出对象成员变量的信息。由于对象类型和成员类型的多样性,所以采取了以下的逻辑:

    在exportObject方法中,当对象类型为Collection和Map类型时,则需要递归调用exportObject进行处理;
    而如果对象类型不是Collection和Map类型的话,将判断对象类是否被Exportable annotation修饰过:
    如果没有被修饰,则直接输出<对象类名>对象.toString()</对象类名>作为xml绑定结果的一部分;
    如果被修饰过,则需要调用exportFields方法对对象的成员变量进行xml绑定。

         在exportFields方法中,首先取出对象的所有成员,然后获得被Persisitent annotation修饰的成员。在其后的一句:field.setAccessible(true)是很重要的,因为bean类定义中的成员访问修饰都是private,所以为了避免java虚拟机检查对私有成员的访问权限,加上这一句是必需的。接着后面的语句便是输出<成员名>成员值</成员名>这样的xml结构。像在exportObject方法中一般,仍然需要判断成员类型是否为Collection和Map类型,如果为上述两种类型之一,则要在exportFields中再次调用exportObject来处理这个成员。

         在main方法中,建立了一个由单个友人地址类(AddressForTest)组成的ArrayList作为通讯录类(AddressForTest)的成员的通讯录对象,并且输出这个对象的xml绑定,运行结果如下:
    <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>

                      [/code]

      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://file.javaxxz.com/2014/10/28/235638734.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-26 02:29 , Processed in 0.363417 second(s), 36 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

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