上篇博客我们说了call()方法,这次我们来展开讨论,call()方法是AbstractHessianOutput中的方法,该方法使用了模板方法设计模式,什么是模板方法设计模式?
举个例子:
我们将使用电脑分为3步。打开电脑,使用,关闭电脑
我们看看在这三步里那几步具有共性,那几步在不同的人身上有不同的体现
第一步:打开电脑,毫无疑问所有人在使用电脑前都要打开电脑
第二步:使用,不同的人使用电脑的目的是不一样的,有的人打开电脑用来办公,有的人打开电脑用来玩游戏,有的人打开电脑用来看视频,等等。。。
第三步:关闭电脑,用完电脑都会关闭
在这三步中因为一、三步具有共性所以我们可以把它们提到父类中,而第二步是不具备共性的所以将第二步放到子类中进行个性化实现
以上大概就是模板方法模式的思想
基本上所有的设计模式都和多态有紧密的联系,所以深刻的理解多态是理解设计模式的基础
public void call(String method, Object []args)
throws IOException
{
int length = args != null ? args.length : 0;
startCall(method, length);
for (int i = 0; i < length; i++)
writeObject(args[i]);
completeCall();
}
我们先来看一下时序图是什么样的
上面代码对应的是时序图中的1.1.1,HessianOutput会调用SerilalizerFactory的getSerializer(Class cl)方法获取到对应的可以序列化cl对象的序列化对象,SerilalizerFactory的loadSerializer(Class<?> cl)方法会完成根据cl对象获取序列化对象的功能
让我们来看看loadSerializer方法具体实现的情况
protected Serializer loadSerializer(Class<?> cl)
throws HessianProtocolException
{
Serializer serializer = null;
for (int i = 0;
_factories != null && i < _factories.size();
i++) {
AbstractSerializerFactory factory;
factory = (AbstractSerializerFactory) _factories.get(i);
serializer = factory.getSerializer(cl);
if (serializer != null)
return serializer;
}
//Hessian第一次获取到Class对象与序列化对象的对应关系后会将这个对应关系放到缓存中,然后每次回去缓存中查找是否有某个Class对象和序列化对象的对应关系
//如果有该对应关系,直接返回就可以了(因为序列化对象是无状态对象,所以所有同一类型的Class对象可以共用一个序列化对象),java中的基本类型和对应的包装类
//Hessian在初始化时就已经把对应关系放到了map里,所以基本类型对象在这里就能拿到对应的Serializer
serializer = _contextFactory.getSerializer(cl.getName());
//缓存中有序列化对应关系,直接返回
if (serializer != null)
return serializer;
ClassLoader loader = cl.getClassLoader();
if (loader == null)
loader = _systemClassLoader;
ContextSerializerFactory factory = null;
factory = ContextSerializerFactory.create(loader);
//如果cl对象有定制化的序列化对象则返回定制的序列化对象,举个例子
//客户端想把一个自定义的对象Person传输到服务端,客户端可以为Person自定义一个序列化对象来做这件事情,但是自定义序列化类一定要符合Hessian的规则
//在Hessian中自定义序列化类一定要遵守两个规则
//1、自定义序列化类名以HessianSerializer结尾,例如Person的自定义序列化类名为PersonHessianSerializer
//2、自定义序列化类要实现Serializer接口,并实现该接口中的writeObject()方法
serializer = factory.getCustomSerializer(cl);
//如果该类有自定义序列化对象返回
if (serializer != null) {
return serializer;
}
//该行代码以下都是用来判断根据cl获取对应的序列化对象,我们会重点挑出几个重点的序列化对象在单独的博客中分析
if (HessianRemoteObject.class.isAssignableFrom(cl)) {
return new RemoteSerializer();
}
else if (BurlapRemoteObject.class.isAssignableFrom(cl)) {
return new RemoteSerializer();
}
else if (InetAddress.class.isAssignableFrom(cl)) {
return InetAddressSerializer.create();
}
else if (JavaSerializer.getWriteReplace(cl) != null) {
Serializer baseSerializer = getDefaultSerializer(cl);
return new WriteReplaceSerializer(cl, getClassLoader(), baseSerializer);
}
else if (Map.class.isAssignableFrom(cl)) {
if (_mapSerializer == null)
_mapSerializer = new MapSerializer();
return _mapSerializer;
}
else if (Collection.class.isAssignableFrom(cl)) {
if (_collectionSerializer == null) {
_collectionSerializer = new CollectionSerializer();
}
return _collectionSerializer;
}
else if (cl.isArray())
return new ArraySerializer();
else if (Throwable.class.isAssignableFrom(cl))
return new ThrowableSerializer(cl, getClassLoader());
else if (InputStream.class.isAssignableFrom(cl))
return new InputStreamSerializer();
else if (Iterator.class.isAssignableFrom(cl))
return IteratorSerializer.create();
else if (Calendar.class.isAssignableFrom(cl))
return CalendarSerializer.SER;
else if (Enumeration.class.isAssignableFrom(cl))
return EnumerationSerializer.create();
else if (Enum.class.isAssignableFrom(cl))
return new EnumSerializer(cl);
else if (Annotation.class.isAssignableFrom(cl))
return new AnnotationSerializer(cl);
return getDefaultSerializer(cl);
}
获取到对应的序列化对象后就可以调用序列化对象的writeObject()方法将将信息写到server端
看到很多博客都写Hessian使用JavaSerializer来进行序列化的,其实在实际的应用场景中基本上都不是用JavaSerializer来做序列化的,后面的博文中也会说到这些