简介我们在上一篇文章中提到,jbossmarshalling是一种非常好的序列化java对象的方式。它兼容JDK自带的序列化,同时也提供了性能和使用上的优化。那么这么优秀的序列化工具能不能用在netty中作为消息传递的方式呢?答案当然是肯定的,netty一切皆有可能。netty中的marshallingprovider回顾一下jbossmarshalling的常见用法。我们需要从MarshallerFactory创建一个Marshaller。因为mashaller有不同的实现,我们需要指定具体的实现来创建MarshallerFactory,如下:MarshallerFactorymarshallerFactory=Marshalling.getProvidedMarshallerFactory("river");这个MarshallerFactory其实就是一个MarshallerProvider。netty中定义了这样一个接口:publicinterfaceMarshallerProvider{MarshallergetMarshaller(ChannelHandlerContextctx)throwsException;}MarshallerProvider其实做的和MarshallerFactory一样的工作。既然MarshallerProvider是一个接口,那么它的实现是什么?在netty中它有两个实现类,分别是DefaultMarshallerProvider和ThreadLocalMarshallerProvider。两者有什么区别?先来看一下DefaultMarshallerProvider:publicclassDefaultMarshallerProviderimplementsMarshallerProvider{privatefinalMarshallerFactoryfactory;私有最终MarshallingConfiguration配置;publicDefaultMarshallerProvider(MarshallerFactoryfactory,MarshallingConfigurationconfig){this.factory=factory;这个.config=配置;}publicMarshallergetMarshaller(ChannelHandlerContextctx)throwsException{returnfactory.createMarshaller(config);}}顾名思义,DefaultMarshallerProvider是marshallerProvider的默认实现。从具体的实现代码可以看出,DefaultMarshallerProvider其实需要传入MarshallerFactory和MarshallingConfiguration作为参数,然后使用传入的MarshallerFactory来创建具体的marshallerProvider,这与我们手动创建marshaller的方式是一致的。但是在上面的实现中,每次getMarshaller都需要从工厂新建一个,性能上可能会出现问题。所以netty又实现了一个新的ThreadLocalMarshallerProvider:publicclassThreadLocalMarshallerProviderimplementsMarshallerProvider{privatefinalFastThreadLocalmarshallers=newFastThreadLocal();私有最终MarshallerFactory工厂;私有最终MarshallingConfiguration配置;publicThreadLocalMarshallerProvider(MarshallerFactoryfactory,MarshallingConfigurationconfig){this.factory=factory;这个.config=配置;}@OverridepublicMarshallergetMarshaller(ChannelHandlerContextctx)throwsException{Marshallermarshaller=marshallers.get();if(marshaller==null){marshaller=factory.createMarshaller(config);marshallers.set(编组器);}返回编组器;}}ThreadLocalMarshallerProvider和DefaultMarshallerProvider的区别在于ThreadLocalMarshallerProvider中保存了一个FastThreadLocal对象,FastThreadLocal是JDK中ThreadLocal的优化版本,比Thr更好eadLocal更快。在getMarshaller方法中,首先从FastThreadLocal获取Marshaller对象。如果Marshaller对象不存在,则从工厂创建一个Marshaller对象,最后将Marshaller对象放到ThreadLocal中。有MarshallerProvider就有和他对应的UnMarshallerProvider:publicinterfaceUnmarshallerProvider{UnmarshallergetUnmarshaller(ChannelHandlerContextctx)throwsException;}netty中的UnmarshallerProvider有三个实现类,分别是DefaultUnmarshallerProvider,ThreadLocalUnmarshallerProvider和ContextBoundUnmarshallerProvider。前面的两个DefaultUnmarshallerProvider,ThreadLocalUnmarshallerProvider和marshaller最重要的是实现是一样的,这里就不重复解释了。下面主要看一下ContextBoundUnmarshallerProvider的实现。我们从名字就可以看出这个unmarshaller是和ChannelHandlerContext相关的。ChannelHandlerContext表示通道的上下文。它有一个方法叫做attr,可以保存通道相关的属性:Attributeattr(AttributeKeykey);ContextBoundUnmarshallerProvider就是把Unmarshaller存放在context中,每次用到的时候从context中获取,没有获取到的时候从factroy中获取。我们来看下ContextBoundUnmarshallerProvider的实现:publicclassContextBoundUnmarshallerProviderextendsDefaultUnmarshallerProvider{privatestaticfinalAttributeKeyUNMARSHALLER=AttributeKey.valueOf(ContextBoundUnmarshallerProvider.class,"UNMARSHALLER");公共ContextBoundUnmarshallerProvider(MarshallerFactory工厂,MarshallingConfiguration配置){超级(工厂,配置);}@OverridepublicUnmarshallergetUnmarshaller(ChannelHandlerContextctx)throwsException{属性attr=ctx.channel().attr(UNMARSHALLER);解组器unmarshaller=attr.get();if(unmarshaller==null){unmarshaller=super.getUnmarshaller(ctx);属性集(解组器);}返回解组器;}}ContextBoundUnmarshallerProvider继承自DefaultUnmarshallerProvider,在getUnmarshaller方法中先从ctx中取出unmarshaller,如果没有则调用DefaultUnmarshallerProvider中的getUnmarshaller方法取出unmarshallerMarshallingencoder上面章节我们拿到了marshaller。接下来,让我们看看如何使用编组器进行编码和解码操作。我们先来看编码器MarshallingEncoder。MarshallingEncoder继承自MessageToByteEncoder,接收的泛型类型为Object:publicclassMarshallingEncoderextendsMessageToByteEncoder