准备用netty+protobuf做一个通讯模块.
在netty官网找到一个LocalTime的一个demo,
class LocalTimeServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline p = Channels.pipeline();
p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance()));
p.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender());
p.addLast("protobufEncoder", new ProtobufEncoder());
p.addLast("handler", new LocalTimeServerHandler());
return p;
}
发现 ProtobufDecoder 是需要一个MessageLite 对象的,也就是要指定所要解析的对象类型,
但在一般应用中这样写死一个对象类型,所有业务中都用这一个数据结构是不太现实的(虽然protobuf是比较灵活的数据结构,但感觉还是会比较臃肿),然后就找动态创建Message 的方法,在官方文档中一眼就看到了一个 DynamicMessage 的对象,里边有findMessageTypeByName(name) ,parserFrom 等来构造消息的方法,很明显肯定就是这个了...
但是所有方法里都会有一个必须的参数 Descriptor 类型的对象,
连到源码中看见他是在Descriptors中的一个内部类
里边有FileDescriptor FieldDescriptor MethodDescriptor EnumDescriptor ServiceDescriptor Descriptor ...
一眼可以看出来这有点类似于java 的反射 Type Field Method ....
FileDescriptor 可以在protobuf 生成的java文件中的静态方法获取到
name.proto Name.getDescriptor();
FileDescriptor file = Project.getDescriptor();
String name = "ByteCode";
Descriptor type = file.findMessageTypeByName(name);
System.out.println(type);
DynamicMessage msg = DynamicMessage.getDefaultInstance(type);
这是我一个Project.proto 文件里有一个 message 为 ByteCode 对象所生成的(有一点要注意的是它不需要包名).
最后担心一个问题是 DynamicMessage 的一些操作可能是要走反射的..
Hi,
I was trying to make Protobuf message self describing and also use the fact that in c++ we can get the instance of the exact message type from the name.
const Descriptor* d = DescriptorPool::generated_
Message * msg = MessageFactory::generated_
msg->ParseFromString("Message data") ;
This seems to work for me well.
But I'm not able to find the equivalent implementation in Java. Is it possible to do the same in Java ?
- Suresh
============================================================
There is no central repository of descriptors in Java. It wouldn't really work because Java normally does not load classes until they are first used, so the descriptors wouldn't appear in the repository until you manually loaded the classes somehow.