Hessian序列化对象之BasicSerializer(五)

来源:互联网 发布:dcp打包软件 编辑:程序博客网 时间:2024/06/02 02:18

在Hessian中所有的序列化对象和反序列化对象都是成对存在的,在接下来分析Hessian序列化对象的博客中,会成对分析,例如本篇分析BasicSerializer的同时也会分析BasicDeserializer

在Hessian中8个基本类型的序列化

boolean,byte,short,int,long,float,double,char

8个基本类型对应的包装类的序列化

Boolean,Byte,Short,Integer,Long,Float,Double,Character

8种基本类型对应的数组

boolean[],byte[],short[],int[],long[],float[],double[],char[]

还有

void,String,Date,String[],Number

上述类型的序列化功能都是由BasicSerializer实现的

Hessian是在ContextSerializerFactory中来初始化上述类对象和序列化对象的对应关系的我们来看一下Hessian是如何做的

ContextSerializerFactory的静态初始化块如下(代码太长,只展示了int类型对应的序列化对象,其余因为篇幅原因省略了)

static {    _staticSerializerMap = new HashMap();    _staticDeserializerMap = new HashMap();    _staticClassNameMap = new HashMap();    addBasic(void.class, "void", BasicSerializer.NULL);    addBasic(Integer.class, "int", BasicSerializer.INTEGER);    addBasic(int.class, "int", BasicSerializer.INTEGER);    addBasic(int[].class, "[int", BasicSerializer.INTEGER_ARRAY);    // hessian/3bb5    _staticDeserializerMap.put(StackTraceElement.class.getName(),                               new StackTraceElementDeserializer());    ClassLoader systemClassLoader = null;    try {      systemClassLoader = ClassLoader.getSystemClassLoader();    } catch (Exception e) {    }    _systemClassLoader = systemClassLoader;  }
在静态初始化块中调用静态方法addBasic()来初始化对应关系,addBasic代码如下,类的基本名称和序列化对象的关系被放到了_staticSerializerMap中(注意调用int的getName方法的返回值为int,而调用Integer方法的返回值为java.lang.Integer,这两者是不一样的),而_staticDeserializerMap和_staticClassNameMap是反序列化相关的,

后面博客讲到反序列化时再详细说明

  private static void addBasic(Class cl, String typeName, int type)  {    _staticSerializerMap.put(cl.getName(), new BasicSerializer(type));    Deserializer deserializer = new BasicDeserializer(type);    _staticDeserializerMap.put(cl.getName(), deserializer);    _staticClassNameMap.put(typeName, deserializer);  }
这里虽然存放了类和序列化对象的对应关系,但是根据类名获取序列化对象的方法是从_serializerClassMap中拿的,而不是_staticSerializerMap,代码如下

  public Serializer getSerializer(String className)  {    Serializer serializer = _serializerClassMap.get(className);    if (serializer == AbstractSerializer.NULL)      return null;    else      return serializer;  }
这是因为在创建ContextSerializerFactory对象时调用了它的init(),在init()方法中将_staticSerializerMap中的内容复制到了_serializerClassMap中

====================

到此为止通过类名已经拿到了对应的序列化对象,这时会调用writeObject()方法真正的将对象写出到流中,让我们看看BasicObject的writeObject()方法是如何实现的(截取部分代码)

 public void writeObject(Object obj, AbstractHessianOutput out)    throws IOException  {    switch (_code) {    case BYTE:    case SHORT:    case INTEGER:      out.writeInt(((Number) obj).intValue());      break;    case STRING:      out.writeString((String) obj);      break;          case STRING_BUILDER:      out.writeString(((StringBuilder) obj).toString());      break;          case DATE:      out.writeUTCDate(((Date) obj).getTime());      break;          case INTEGER_ARRAY:    {      if (out.addRef(obj))        return;            int []data = (int []) obj;            boolean hasEnd = out.writeListBegin(data.length, "[int");            for (int i = 0; i < data.length; i++)        out.writeInt(data[i]);      if (hasEnd)        out.writeListEnd();            break;    }    case CHARACTER_ARRAY:    {      char []data = (char []) obj;      out.writeString(data, 0, data.length);      break;    }    case OBJECT_ARRAY:    {      if (out.addRef(obj))        return;            Object []data = (Object []) obj;            boolean hasEnd = out.writeListBegin(data.length, "[object");            for (int i = 0; i < data.length; i++) {        out.writeObject(data[i]);      }      if (hasEnd)        out.writeListEnd();      break;    }        case NULL:      out.writeNull();      break;        case OBJECT:      ObjectHandleSerializer.SER.writeObject(obj, out);      break;    case BYTE_HANDLE:      out.writeObject(new ByteHandle((Byte) obj));      break;    case SHORT_HANDLE:      out.writeObject(new ShortHandle((Short) obj));      break;    case FLOAT_HANDLE:      out.writeObject(new FloatHandle((Float) obj));      break;    default:      throw new RuntimeException(_code + " unknown code for " + obj.getClass());    }  }
实际上BasicSerializer是调用了HessianOutput的write***()方法将信息写出到流中的,具体代码如下

向流中写一个int类型的变量

  public void writeInt(int value)    throws IOException  {    os.write('I');    os.write(value >> 24);    os.write(value >> 16);    os.write(value >> 8);    os.write(value);  }

其余的write***()方法就不一一展示了,有兴趣的同学可以去GitHub上下载Hessian的源码看一下HessianOutput类具体是如何实现的

当把服务端收到客户端序列化过来的对象后会进行反序列化,下面来看一下BasicDeserializer的readObject()方法是如何实现的,可以看到反序列化调用的是AbstractHessianInput的实现类HessianInput的方法来实现的

public Object readObject(AbstractHessianInput in)    throws IOException  {    switch (_code) {    case NULL:      // hessian/3490      in.readObject();            return null;          case BOOLEAN:      return Boolean.valueOf(in.readBoolean());          case BYTE:      return Byte.valueOf((byte) in.readInt());          case SHORT:      return Short.valueOf((short) in.readInt());          case INTEGER:      return Integer.valueOf(in.readInt());    case LONG:      return Long.valueOf(in.readLong());    case FLOAT:      return Float.valueOf((float) in.readDouble());    case DOUBLE:      return Double.valueOf(in.readDouble());          case STRING:      return in.readString();          case OBJECT:      return in.readObject();          case CHARACTER:      {        String s = in.readString();        if (s == null || s.equals(""))          return Character.valueOf((char) 0);        else          return Character.valueOf(s.charAt(0));      }          case CHARACTER_OBJECT:      {        String s = in.readString();        if (s == null || s.equals(""))          return null;        else          return Character.valueOf(s.charAt(0));      }          case DATE:      return new Date(in.readUTCDate());          case NUMBER:      return in.readObject();    case BYTE_ARRAY:      return in.readBytes();    case CHARACTER_ARRAY:    {      String s = in.readString();      if (s == null)        return null;      else {        int len = s.length();        char []chars = new char[len];        s.getChars(0, len, chars, 0);        return chars;      }    }    case BOOLEAN_ARRAY:    case SHORT_ARRAY:    case INTEGER_ARRAY:    case LONG_ARRAY:    case FLOAT_ARRAY:    case DOUBLE_ARRAY:    case STRING_ARRAY:    {      int code = in.readListStart();      switch (code) {      case 'N':        return null;      case 0x10: case 0x11: case 0x12: case 0x13:      case 0x14: case 0x15: case 0x16: case 0x17:      case 0x18: case 0x19: case 0x1a: case 0x1b:      case 0x1c: case 0x1d: case 0x1e: case 0x1f:        int length = code - 0x10;        in.readInt();        return readLengthList(in, length);      default:        String type = in.readType();        length = in.readLength();        return readList(in, length);      }    }    default:      throw new UnsupportedOperationException();    }  }

下面这段代码就是HessianInput类的readInt方法,可以看到先从流中读取了一个字节,通过该字节来判断接下来的变量是boolean类型的还是int类型还是其他类型

  public int readInt()    throws IOException  {    int tag = read();    switch (tag) {    case 'T': return 1;    case 'F': return 0;    case 'I': return parseInt();    case 'L': return (int) parseLong();    case 'D': return (int) parseDouble();          default:      throw expect("int", tag);    }  }



思考一个问题

为什么要把写基本类型到流中的实现比如writeInt()方法在HessianOutput中实现而不是在BasicSerializer中实现呢?