Hessian序列化对象之BasicSerializer(五)

在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中实现呢?



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值