`
leonzhx
  • 浏览: 793841 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Java Generated Code

 
阅读更多

1.   The protocol buffer compiler produces Java output when invoked with the --java_out command-line flag. It creates a single .java for each .proto file input. This file contains a single outer class definition containing several nested classes and static fields based on the declarations in the .proto file.

 

 

2.   The outer class's name is chosen as follows: If the .proto file contains a java_outer_classname option, then the outer class name will be the value of the option. Otherwise, the outer class name is determined by converting the .proto file base name to camel case. For example, foo_bar.proto will become FooBar .

 

3.  Each message defined in the .proto file will be compiled to a static inner class of the outer class for that .proto file. You should not define a message with same name as the outer class.

 

4.   The protocol buffer compiler generates a static inner class for each message which implements the Message interface. The class is declared final; no further subclassing is allowed. It extends GeneratedMessage . By default, the generated class overrides many methods of GeneratedMessage with specialized versions for maximum speed. If you use “optimize_for = CODE_SIZE; ” option, the generated class will override only the minimum set of methods necessary to function and rely on GeneratedMessage 's reflection-based implementations of the rest. If you use “optimize_for = LITE_RUNTIME; ” option, the generated class will include fast implementations of all methods, but will implement the MessageLite interface, which only contains a subset of the methods of Message . In particular, it does not support descriptors or reflection. In this mode, the generated code only needs to link against libprotobuf-lite.jar instead of libprotobuf.jar .

 

5.   Message objects are immutable. To construct a message object, you need to use a builder. Each message class has its own builder class. The protocol buffer compiler generates a nested class Foo.Builder (suppose message name is “Foo ”) which can be used to build a Foo . Foo.Builder implements the Message.Builder interface. It extends the GeneratedMessage.Builder class. Methods that modify the contents of a builder – including field setters – always return a reference to the builder. This allows multiple method calls to be chained together in one line. The build() method of the Builder can generate the message instance.

 

6.   The protocol buffer compiler generates a set of accessor methods for each field defined within the message in the .proto file. The methods that read the field value are defined both in the message class and its corresponding builder; the methods that modify the value are only defined in the builder only.

 

7.   As well as accessor methods, the compiler generates an integer constant for each field containing its field number. The constant name is the field name converted to upper-case followed by _FIELD_NUMBER . For example, given the field optional int32 foo_bar = 5; the compiler will generate the constant public static final int FOO_BAR_FIELD_NUMBER = 5; .

 

8.   For either of these field definitions:

optional int32 foo = 1;

required int32 foo = 1; 
 

The compiler will generate the following accessor methods in both the message class and its builder:

a)   bool hasFoo() : Returns true if the field is set.

b)  int getFoo() : Returns the current value of the field. If the field is not set, returns the default value.

The compiler will generate the following methods only in the message's builder:

a)   Builder setFoo(int value) : Sets the value of the field. After calling this, hasFoo() will return true and getFoo() will return value.

b)   Builder clearFoo() : Clears the value of the field. After calling this, hasFoo() will return false and getFoo() will return the default value.

If the attribute type is a message instead of int , setFoo() also accepts an instance of the message's builder type as the parameter. This is just a shortcut which is equivalent to calling .build() on the builder and passing the result to the method.

 

9.   For this field definition:

repeated int32 foo = 1;
 

  The compiler will generate the following accessor methods in both the message class and its builder:

 

a)   int getFooCount() : Returns the number of elements currently in the field.

b)  i nt getFoo(int index) : Returns the element at the given zero-based index.

c)   List<Integer> getFooList() : Returns the entire field as an immutable list.

The compiler will generate the following methods only in the message's builder:

a)   Builder setFoo(int index, int value) : Sets the value of the element at the given zero-based index.

b)   Builder addFoo(int value) : Appends a new element to the field with the given value.

c)   Builder addAllFoo(List<Integer> value) : Appends all elements in the given list to the field.

d)  Builder clearFoo() : Removes all elements from the field. After calling this, getFooCount() will return zero.

If the attribute type is a message instead of int , setFoo() and addFoo() also accept an instance of the message's builder type as the parameter. This is just a shortcut which is equivalent to calling .build() on the builder and passing the result to the method.

 

10.   Given an enum definition like:

enum Foo {

  VALUE_A = 1;

  VALUE_B = 5;

  VALUE_C = 1234;

}
 

The protocol buffer compiler will generate a Java enum type called Foo with the same set of values and the following special methods:

 

a)   int getNumber() : Returns the object's numeric value as defined in the .proto file.

b)   EnumValueDescriptor getValueDescriptor() : Returns the value's descriptor, which contains information about the value's name, number, and type.

c)   EnumDescriptor getDescriptorForType() : Returns the enum type's descriptor, which contains e.g. information about each defined value.

Additionally, the Foo enum type contains the following static methods:

a)   static Foo valueOf(int value) : Returns the enum object corresponding to the given numeric value.

b)   static Foo valueOf(EnumValueDescriptor descriptor) : Returns the enum object corresponding to the given value descriptor. May be faster than valueOf(int) .

c)   EnumDescriptor getDescriptor() : Returns the enum type's descriptor, which contains e.g. information about each defined value. (This differs from getDescriptorForType() only in that it is a static method.)

An integer constant is also generated with the suffix _VALUE for each enum value.

 

11.   .proto language allows multiple enum symbols to have the same numeric value:

enum Foo {

  BAR = 1;

  BAZ = 1;

}
 

In this case, BAZ is a synonym for BAR . In Java, BAZ will be defined as a static final field like so:

 

static final Foo BAZ = BAR;
 

 

Thus, BAR and BAZ compare equal, and BAZ should never appear in switch statements. The compiler always chooses the first symbol defined with a given numeric value to be the "canonical" version of that symbol; all subsequent symbols with the same number are just aliases.

 

12.   For messages containing sub-messages, the compiler also generates sub builders. For the following message definition :

message Foo {

  optional int32 val = 1;

  // some other fields.

}

 

message Bar {

  optional Foo foo = 1;

  // some other fields.

}

 

message Baz {

  optional Bar bar = 1;

  // some other fields.

}
 

If you have a Baz message already, Instead of:

 

 

baz = baz.toBuilder().setBar(

      baz.getBar().toBuilder().setFoo(

          baz.getBar().getFoo().toBuilder().setVal(10).build()

      ).build()).build(); 
 

 

You can write:

 

Baz.Builder builder = baz.toBuilder();

  builder.getBarBuilder().getFooBuilder().setVal(10);

  baz = builder.build(); 
 

 

 

   

13.   In addition to the Message interface, the generated class (suppose its name is Foo ) defines the following static methods:

a)   static Foo getDefaultInstance() : Returns a singleton instance of Foo , which is identical to what you'd get if you called Foo.newBuilder().build() (so all singular fields are unset and all repeated fields are empty). Note that the default instance of a message can be used as a factory by calling its newBuilderForType() method.

b)   static Descriptor getDescriptor() : Returns the type's descriptor. This contains information about the type, including what fields it has and what their types are. This can be used with the reflection methods of the Message , such as getField() .

c)   static Foo parseFrom(...) : Parses a message of type Foo from the given source and returns it. There is one parseFrom method corresponding to each variant of mergeFrom() in the Message.Builder interface. Note that parseFrom() never throws UninitializedMessageException ; it throws InvalidProtocolBufferException if the parsed message is missing required fields. This makes it subtly different from calling Foo.newBuilder().mergeFrom(...).build() .

d)   Foo.Builder newBuilder() : Creates a new builder.

e)   Foo.Builder newBuilder(Foo prototype) : Creates a new builder with all fields initialized to the same values that they have in prototype. Since embedded message and string objects are immutable, they are shared between the original and the copy.

 

14.   Given a message with an extension range:

message Foo {

  extensions 100 to 199;

}
 

The protocol buffer compiler will make Foo extend GeneratedMessage.ExtendableMessage instead of the usual GeneratedMessage . Similarly, Foo 's builder will extend GeneratedMessage.ExtendableBuilder . You should never refer to these base types by name (GeneratedMessage is considered an implementation detail). Foo and Foo.Builder will inherit the methods hasExtension() , getExtension() , and getExtensionCount() . Additionally, Foo.Builder will inherit methods setExtension() and clearExtension() . Each of these methods takes, as its first parameter, an extension identifier, which identifies an extension field. The remaining parameters and the return value are exactly the same as those for the corresponding accessor methods that would be generated for a normal (non-extension) field of the same type as the extension identifier.

 

Given an extension definition:

extend Foo {

  optional int32 bar = 123;

}
 

The protocol buffer compiler generates an "extension identifier" called bar as a static field of the outer class for the .proto file, which you can use to access this extension:

Foo foo =  Foo.newBuilder().setExtension(bar, 1) .build();
assert foo.hasExtension(bar);
assert foo.getExtension(bar) == 1;
 

 

When parsing a message that might have extensions, you must provide an ExtensionRegistry in which you have registered any extensions that you want to be able to parse. Otherwise, those extensions will just be treated like unknown fields:

ExtensionRegistry registry = ExtensionRegistry.newInstance();
  registry.add(bar);
  Foo foo = Foo.parseFrom(input, registry);
 

 


 

15.   Given a service definition:

service Foo {

  rpc Bar(FooRequest) returns(FooResponse);

}
 

The protocol buffer compiler will generate an abstract class Foo to represent this service. Foo will have an abstract method for each method defined in the service definition. In this case, the method Bar is defined as:

 

abstract void bar(RpcController controller, FooRequest request,
                  RpcCallback <FooResponse> done);
 

 

The parameters are equivalent to the parameters of Service.CallMethod() , except that the method argument is implied and request and done specify their exact type.

Foo subclasses the Service interface. The protocol buffer compiler automatically generates implementations of the methods of Service as follows:

a)   getDescriptorForType : Returns the service's ServiceDescriptor .

b)   callMethod : Determines which method is being called based on the provided method descriptor and calls it directly, down-casting the request message and callback to the correct types.

c)   getRequestPrototype and getResponsePrototype : Returns the default instance of the request or response of the correct type for the given method.

The following static method is also generated:

a)   static ServiceDescriptor getDescriptor() : Returns the type's descriptor, which contains information about what methods this service has and what their input and output types are.

Foo will also contain a nested interface Foo.Interface . This is a pure interface that again contains methods corresponding to each method in your service definition. However, this interface does not extend the Service interface. This is a problem because RPC server implementations are usually written to use abstract Service objects, not your particular service. To solve this problem, if you have an object impl implementing Foo .Interface, you can call Foo.newReflectiveService(impl) to construct an instance of Foo that simply delegates to impl , and implements Service .

To recap, when implementing your own service, you have two options:

a)   Subclass Foo and implement its methods as appropriate, then hand instances of your subclass directly to the RPC server implementation. This is usually easiest, but some consider it less "pure".

b)   Implement Foo.Interface and use Foo.newReflectiveService(Foo.Interface) to construct a Service wrapping it, then pass the wrapper to your RPC implementation.

 

16.   The protocol buffer compiler also generates a "stub" implementation of every service interface, which is used by clients wishing to send requests to servers implementing the service. For the Foo service (above), the stub implementation Foo.Stub will be defined as a nested class.

Foo.Stub is a subclass of Foo which also implements the following methods:

a)   Foo.Stub(RpcChannel channel) : Constructs a new stub which sends requests on the given channel.

b)   RpcChannel getChannel() : Returns this stub's channel, as passed to the constructor.

The stub additionally implements each of the service's methods as a wrapper around the channel. Calling one of the methods simply calls channel.callMethod() .

 

17.   The Protocol Buffer library does not include an RPC implementation. However, it includes all of the tools you need to hook up a generated service class to any arbitrary RPC implementation of your choice. You need only provide implementations of RpcChannel and RpcController .

 

18.   The RPC classes all have non-blocking semantics: when you call a method, you provide a callback object which will be invoked once the method completes. The protocol buffer compiler also generates blocking versions of your service class. Foo.BlockingInterface is equivalent to Foo.Interface except that each method simply returns the result rather than call a callback. So, for example, bar is defined as:

abstract FooResponse bar(RpcControllercontroller, FooRequest request)
                         throws ServiceException ;
 

 

Analogous to non-blocking services, Foo.newReflectiveBlockingService(Foo.BlockingInterface) returns a BlockingService wrapping some Foo.BlockingInterface . Finally, Foo.BlockingStub returns a stub implementation of Foo.BlockingInterface that sends requests to a particular BlockingRpcChannel .

分享到:
评论

相关推荐

    protobuf 中文操作手册

    `Protocol Buffers Java Generated Code.pdf`涵盖了Java生成的类的使用。每个消息类型都会生成一个类,字段对应类中的成员变量。提供有`parseFrom()`方法用于解析数据,`toByteArray()`用于序列化。 5. **基本概念...

    protocol 官网相关文档

    从谷歌官网下载一些文件,Encoding.txt, Java Generated Code.txt,Language Guide.txt,Protocol Buffer Basics Java.txt,Style Guide.txt。

    添加java源码-gradle-generated-code:一个小型gradle插件,为生成的代码添加了Java源集

    ch.romasch.gradle.generated-code ' ) project . generate . dependsOn project . tasks . withType( MyPluginTask ) } } 如何使用它 目前,该插件尚未在任何地方发布或注册。 要在本地使用它: git克隆仓库 ./...

    程序员必备-codetemplates.zip

    我们可以看到Eclipse Code Templates界面中间Configure generated code and comments区域包含了两个菜单树:Comment、Code, Comments代表注释模板,Code代表代码模板,其中每一个子菜单代表子项的模板。 当我们...

    自动生成mapper和dao工具Auto_Generated_Code

    这个工具不用向idea和eclipse在集成mybaitis的插件,直接在运行好把生成的pojo和mapper拷贝到项目中即可,使用方式首先把数据库链接配置到generatorConfig.xml后,cmd进入到这个文件夹下运行:java -jar mybatis-...

    java解析wsdl文档获取方法与参数

    codeModel.build(new File("target/generated-sources")); ``` 这样,你就有了一个可以直接调用的Java客户端,包含了所有从WSDL中解析出的方法和参数。 总结,Java解析WSDL文档获取方法与参数涉及到的技术点包括:...

    《Java Design Patterns》高清完整PDF版

    Learn how to implement design patterns in Java: each pattern in Java Design Patterns is a complete implementation and the output is generated using Eclipse, making the code accessible to all....

    windowbuilder pro 3

    Use the visual designer and Java code will be generated for you. You can easily add controls using drag-and-drop, add event handlers to your controls, change various properties of controls using a ...

    windowbuilder pro 4

    Use the visual designer and Java code will be generated for you. You can easily add controls using drag-and-drop, add event handlers to your controls, change various properties of controls using a ...

    windowbuilder pro 1

    Use the visual designer and Java code will be generated for you. You can easily add controls using drag-and-drop, add event handlers to your controls, change various properties of controls using a ...

    windowbuilder pro 2

    Use the visual designer and Java code will be generated for you. You can easily add controls using drag-and-drop, add event handlers to your controls, change various properties of controls using a ...

    java生成二维码(qrcodeutil.java)

    System.out.println("QR Code generated and saved to output.png"); } catch (Exception e) { e.printStackTrace(); } } ``` 7. **拓展功能**: - 添加自定义logo:在二维码中间添加企业或应用的logo。 - ...

    Java二维码生成工具

    System.out.println("QR Code generated successfully at: " + outputFile.getAbsolutePath()); } catch (WriterException | IOException e) { e.printStackTrace(); } } } ``` 这段代码会生成一个指定大小...

    java反编译工具 jad

     -disass - 不用用字节码的方式反编译 (no JAVA source generated)  -f - 输出整个的名字,无论是类还是方法  -ff -输出类的成员在方法之前 (default: after methods)  -i - 输出所有的变量的缺省的最初值 ...

    Java2Pas,jar包转换delphi

    Java2Pas is a converter to create Delphi .pas source code files from android .class or .jar files. Usage: Java2Pas |.jar&gt; [outputpath] 1.4.0 20140506 - Corrected accidental insertion of local ...

    使用FreeMarker生成java代码

    这样,`generatedCode`就包含了根据模板和数据模型生成的Java代码字符串,你可以将其写入到文件中,或者直接在内存中使用。 FreeMarker与其他工具如Velocity、Thymeleaf等相比,具有灵活性高、性能优秀、易于学习等...

    Deep Learning: Practical Neural Networks with Java 完整高清英文azw3版

    Apply the code generated in practical examples, including weather forecasting and pattern recognition In Detail Machine learning applications are everywhere, from self-driving cars, spam detection, ...

    java生成二维码并保存到本地

    System.out.println("QR Code generated and saved to: " + filePath); } catch (WriterException | IOException e) { e.printStackTrace(); } } } ``` 这段代码会生成一个包含指定字符串的二维码,并将其保存...

    java 二维码相关Jar

    System.out.println("Generated QR code: " + file.getAbsolutePath()); } catch (IOException e) { e.printStackTrace(); } } } ``` #### 四、总结 通过上述介绍可以看出,Java在处理二维码方面提供了多种...

    JAVA编写的计算器

    import java.awt.BorderLayout; import java.awt.Button; import java.awt.Container; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt....

Global site tag (gtag.js) - Google Analytics