XStream注解开启(注解扫描)方式

 先附上XStream官方文档和API地址:

官方文档:http://x-stream.github.io/annotations-tutorial.html

API文档:http://x-stream.github.io/javadoc/

XStream注解开启(注解扫描)方式_第1张图片

 这种通过使用XStream的注解,来完成相关配置开发,必须要开启注解以保证注解生效,否则注解无效,默认注解是不生效的。
如下图,未开启注解序列化的XML如下,默认注解未生效:

XStream注解开启(注解扫描)方式_第2张图片


 开启注解检测的方式有两种,一种调用processAnnotations(),另一种调用autodetectAnnotations()。

两种方式区别在于
第一种方式:
调用processAnnotations,该方法有两种重载形式,如下图

XStream注解开启(注解扫描)方式_第3张图片

 参数可以传Class类对象,或者传Class类对象数组,这样你可以选择开启某一个类的注解或者开启某些类的注解。也就是仅认为某个类的注解有效或者某些类。
如下为参考代码:

public static String objToXML(Object xmlData) throws Exception{
        String postDataXML;
        try {
            //指定解析编码为GBK,并解决XStream对出现双下划线的bug
            XStream xStreamForReqData = new XStream(new DomDriver("GBK", new                 
            XmlFriendlyNameCoder("-_", "_")));
            //开启当前将被序列化为XML的类的注解
            xStreamForReqData.processAnnotations(xmlData.getClass());
            //将要提交给API的数据对象转换成XML格式数据Post给API
            String postDataXMLOld = xStreamForReqData.toXML(xmlData);
            postDataXML = postDataXMLOld.replace(""", "\"");
            //为Bean转换后的XML加上头信息
            postDataXML = XML_TAG + postDataXML;
        } catch (Exception e) {
            logger.error("Object converts into XML go wrong", e);
            throw e;
        }
        return postDataXML;
    }

第二种方式:
调用autodetectAnnotations() 如下图

XStream注解开启(注解扫描)方式_第4张图片

该方法设置注解映射器的自动检测模式,true为开启。需注意,这种方式是在延迟加载模式下运行XStream,在这种模式下,它在处理对象时自动检测注解,并动态配置XStream实例。该方法相当于对使用到的所有实例XStream注解生效。
如下为参考代码:

    static {
        //指定解析编码为GBK,并解决XStream对出现双下划线的bug
        xStreamForReqData = new XStream(new DomDriver("GBK", new XmlFriendlyNameCoder("-_", 
        "_")));
        //开启注解(在类加载时调用一次,在后续每次调用序列化方法时会开启当前类的注解)
        xStreamForReqData.autodetectAnnotations(true);
    }

    public static String objToXML(Object xmlData) throws Exception{
        String postDataXML;
        try {
            //将要提交给API的数据对象转换成XML格式数据Post给API
            String postDataXMLOld = xStreamForReqData.toXML(xmlData);
            postDataXML = postDataXMLOld.replace(""", "\"");
            //为Bean转换后的XML加上头信息
            postDataXML = XML_TAG + postDataXML;
        } catch (Exception e) {
            logger.error("Object converts into XML go wrong", e);
            throw e;
        }
        return postDataXML;
    }

开启了注解后,这里为别名注解生效后的序列化结果:

XStream注解开启(注解扫描)方式_第5张图片


 注意:也正是基于这种懒加载的机制,所带来的问题,在官方文档中也有说明,一下为详细解释。
1、XStream实例缓存为注解处理的所有类类型。每次XStream转换一个对象时,它将在自动检测模式下首先处理对象的类型和所有相关的类型。因此,将对象序列化为XML是没有问题的,因为XStream已经加载了该类,扫描了注解,预先知道了其中的所有类型。
在反序列化时不再是这样。XStream必须知道别名才能将其转换为适当的类型,但是只有在预先处理了该类型之后,它才能找到别名的注释。因此,如果类型还没有反序列化,则反序列化将失败。这一点将在 ”XStream反序列化的坑“ 一文中详细分析。


2、XStream这种懒加载注解开启方式,定义了在处理对象时应用注解配置。因此,自动检测模式将把XStream的序列化过程变成一个线程不安全的操作。当XStream同步配置修改时,它不能保护并发读取,您可能在某些情况下遇到并发问题。
也就是说在单例情况下processAnnotations这种方式已经在序列化前预加载了,所以即使多线程序列化,比如A线程该实例注解加载完了,准备序列化,此时B线程刚开始加载该实例注解,但不会影响A线程,因为已经加载到内存中了(加载过了),这种顶多是重复一遍的加载,但不会存在安全性问题。而autodetectAnnotations这种懒加载是在序列化过程中去加载,会存在多线程之间不同步问题,比如A线程序列化到第二个字段了,加载了别名注解"sex",但此时B线程刚开始序列化第一个字段可能加载的别名注解"name",这样可能就会导致A线程序列化字段名出错。


3、XStream使用定义良好的异常层次结构。如果是第一种预加载的方式,那么只有在序列化前,加载XStream注解时才会抛出InitializationException。如果注解是动态懒加载处理的,它们显然是在序列化过程中抛出。


4、因为预加载,所以不会影响序列化的性能。但懒加载因为是在序列化过程中去加载注解,所以可能会给整个序列化过程带来性能影响。

你可能感兴趣的:(XStream)