preface

There are a lot of use in the android development to the annotation processor (annotation processing) framework, such as common Butterknife Dagger2, EventBus etc., use the annotation processor framework greatly simplifies our code. This section focuses on the principle of custom annotation handlers.

knowledge

When customizing annotations, you generally need to know the following:

  • AbstractProcessor
  • Knowledge about auto-service
  • Knowledge of Javapoet

AbstractProcessor profile

In the early (compiler) optimization section of Understanding the Java Virtual Machine, when a. Java file is compiled into a. Class file using javac. The compilation process can be roughly divided into three processes:

  • The process of parsing and populating symbol tables
  • Annotation processing by the plug-in annotation processor
  • Analysis and bytecode generation process

The annotation processing of the plug-in annotation processor is mainly a call to the AbstractProcessor class. So, when we customize a subclass of this class, the compiler will execute the methods in that class.

Annotation support has been around since JDK1.5, but at this point annotations are only useful at run time. Starting with JDK1.6, a standard API provides plug-in annotation handlers to process annotations at compile time. This requires that we rely on JDK versions higher than 1.6(inclusive).

In the JavAC source code, the plug-in annotation handler is initialized in the initProcessAnnotations() method and executed in the processAnnotations() method, which determines whether a new annotation handler needs to be executed, If there is one, through the com. Sun. View javac. Processing. DoProcessing JavacProcessingEnvironment class () method to generate a new JavaCompiler object to compile the next steps for processing.

The annotation processor is called in javAC source code, and a compiler plug-in is implemented through the annotation processor API. We need to inherit abstract class javax.mail. The annotation. Processing. AbstractProcessor, rewrite the abstract method process (), the method in the javac compiler in execution when the annotation processor code. This method takes two arguments, the first representing the set of annotations processed by the annotation processor, and the second, roundEnvironment, representing the syntax tree nodes in the current Round, each representing an Element. Element includes the following elements: PACKAGE, ENUM, CLASS, ANNOTATION_TYPE, INTERFACE, etc.

AbstractProcessor is a class we use in Android development that handles annotations when the JDK is compiled via javac. This class is removed from the Android SDK, so we need to create a Java Library to get this class. So far, we have a general understanding of AbstractProcessor class execution timing and creation methods.

A subclass of the custom AbstractProcessor is now available, but to be executed at compile time, we need to register our custom annotation processor (that is, the library as a JAR package) with javac so that our custom annotation processor methods will be called at javac compile time. So how to set the jar package. This brings us to the auto-service library below.

Auto – service introduction

Normally, the steps to register a custom processor with javAC are as follows:

  1. In the SRC/main directory to create the resources/meta-inf/services/javax.mail annotation. Processing. Processor file.
  2. In the javax.mail. The annotation. Processing. Processor writes a custom Processor’s full name, if have a Processor, write a line. As follows:
com.soulmate.processor.MyProcessor
Copy the code

This way, at JavAC compile time, our custom annotation handler will be executed while processing the annotation handler.

The auto-service library is designed to solve the problem that this is a manual setup, but each time it is configured it is cumbersome to write, and if I change the class name of the custom AbstractAnnotation subclass, I may forget to do so and cause an error. It does this automatically by adding the @AutoService(Processor.class) annotation to the custom annotation handler class. This can also avoid the problems mentioned above. For specific use, please check the official documentation.

At this point custom annotation handlers can be executed at compile time, so what does Javapoet do? In the process() method of the custom annotation processor, we often need to generate the required Java classes. For this, we can refer to the Process () method of the ButterKnifeProcessor class in the ButterKnife framework. In this case, javapoet is used to generate the required class, with the findViewById() method defined in the generated class.

Javapoet profile

Javapoet is an open source Java generation library for Square.

JavaPoet is a Java API for generating `.java` source files
Copy the code

Javapoet is relatively simple to use and is explained in great detail in the official documentation. So here is not more introduction, specific use can see the official website of the example.

conclusion

Here on the entire custom annotation processor process is introduced, mainly introduced here is the compiler annotation processor. Includes the entire compile-time annotation invocation flow in the source code.