Overview of code generation methods I have used

During this time, I have done a lot of things related to development efficiency, involving many methods and ideas of code generation, which are summarized as follows. Generated code is divided into two parts: code analysis generation tool and code template

tool

Sort by writing difficulty

live template

This is a simple tool of intellij, which seems to be some encapsulation of freemarker or regular replacement. Delegate schemes are of course the built-in ones.
Creation is simple: https://www.jetbrains.org/intellij/sdk/docs/tutorials/live_templates/template_support.html
It is worth noting that more complex matches can be specified in the Edit variables place, resulting in richer code.

Advantages of this scheme:

  • No development tools required
  • Have a certain ability to judge the current environment (edit variables)

shortcoming:

  • Strong dependence on IDE
  • ability too weak

Config file

The representative scheme is GreenDao .
The process of generating code is independent of the app compilation process. That is, there is a main method of the Java console, and executing this method can generate code at the specified location according to config. If you want to integrate this into the compilation process, you need to use the gradle task to call the jar package before all compilation.
GreenDao cleverly uses Java code as the Config file, which greatly simplifies the complexity of the code generation tool. In the timing generation process, you can use json, xml, etc. as configuration files (Spring mode), which is not much different from writing code, but saves the compilation time of complex tools.

Advantages of this scheme:

  • Simple tooling
  • Generated object code has some flexibility

shortcoming:

  • The ability to understand and analyze existing classes is basically 0, and it is difficult to do complex automatic generation.
  • The embedded packaging process is relatively rigid

Annotation Processor

This is the most common solution at present, and I personally feel that ButterKnife and Android annotation can be used as representatives.
The process of generating code is the built-in hook point of Java compilation, which is very secure and compatible. Java itself provides a complete code analysis system of javax.lang.model, which can analyze the existing code very well. However, the conversion between element and typemirror, and the acquisition of class names are very easy to get confused.
The whole tool is relatively simple to write: tutorial . But once there is a positive (how to do xxx) problem, it is difficult to find know-how people. Debugging of reverse problems (bugs) is very simple, because the generated code is visible and breakpointable (cannot be modified).
There are several personal understandings of what apt can do: generate boilerplate code, such as ButterKnife; generate code at compile time to reduce reflection, Subscriber Index of EventBus 3.0 , and later I will open source an apt without reflection to read the value by field name Tool; class validity check, which only apt can do.
Advantages of this scheme:

  • The tool is relatively simple to write and does not require esoteric knowledge
  • The understanding of the code is very, very good, and it can basically do the most extreme class analysis
  • Debug is extremely easy
  • The speed is relatively fast (if the number of repeated apt rounds is relatively small), the technology is still popular

shortcoming:

  • There are very few documents and related materials for javax.lang.model
  • Existing classes cannot be modified
  • Dependencies and visibility relationships must be respected

AspectJ

This is a general technique, although wearing the hat of AOP, it is often used to generate code. Hugo is a very good example, there is a general plugin to use AspectJ under Android project, and the aspect is very simple and easy to understand. The documentation
itself is relatively complete, but the index is messy. The specific hook should be based on the gradle plugin (not studied in detail). The bottom layer is based on ASM, and there is no compatibility problem when it is mature. The analysis of existing classes basically relies on a fixed matching mechanism, more on strings and regularities, and it is not easy to analyze deeper class behaviors (which are originally used to define aspects), and for aspects, it is possible to The contextual information obtained is relatively limited. For extended information, it is mostly based on aspectj language that does not apply to Android, which is a headache. Advantages of this scheme:

  • Modify existing classes instead of generating new ones
  • Compared with other methods of modifying classes, it is more widely used (Spring) and more stable.

shortcoming:

  • The style, location, and context of class understanding and code generation are limited, and it is mainly suitable for large-scale, repetitive and simple work
  • Dependencies are required at runtime
  • When the hook method is used, many classes are generated, which increases the number of calls, and the runtime performance has potential risks. Simple details
  • The debug line numbers are all wrong, which is basically a kneeling. Even decompilation is difficult to understand (the generated functions are quite confusing)

Javassist

Javassist is the closest tool to apt for code modification. There is an example project that can be used as a template.
There are documents , but the more useful ones are limited to the official tutorial. The content of the documents is comparable to javax.lang.model, which is completely incomprehensible. If you want to embed the packaging process, you must write the plugin and transform yourself, there are many pits and there are not many materials. For class matching and traversal, manual writing is required, which is much higher than the complexity of apt. Of course, the real processing is also more complicated. The Groovy language itself is also a big slot. When it is compiled, it can pass everything, and when it is running, everything hangs. The main advantage is the ability to modify classes and ignore dependencies.

Advantages of this scheme:

  • The generated code templates can be sourced from a wide range and have good readability (basically normal Java)
  • The matching logic can be very complex. If used with apt, it can be written relatively simply.
  • It can be completely separated from the normal dependency path, and the transform can be arbitrarily dependent on the package.
  • Decompile the modified class, the code readability is better
  • It is to insert code, not to proxy the method (compared to AspectJ), the performance is more guaranteed

shortcoming:

  • A series of additional operations such as handwritten plugin, transform, matching, etc. are required
  • groovy
  • Debug capability unknown

ASM

ASM is the ultimate super god plan, directly engage in bytecode. Just understand an open source project . Handwritten plugin and transform are also required. The difference from javassist is mainly in the form of code and the way of traversing the code (tree visitor vs structured object). Too many comments.

AST

Specialized in code analysis, to be added.

template

handwriting

Only use it when it's extremely simple or when no template is available, otherwise it's your own fault.

freemarker

Generic technology, no optimizations for java.
advantage:

  • Flexible enough, input Map output String
  • There is a template file with placeholders, easy to modify

shortcoming:

  • No support for the Java language, poor formatting and import

JavaPoet

The special library generated for Java has very good support for import and replacement.
advantage:

  • Structure, easy to use
  • Import, indentation support is very good

shortcoming:

  • It is not easy to have a template template file, and most of the modifications need to read through the code

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325836942&siteId=291194637