Java compile-time annotations automatically generate code

Source: Internet
Author: User


Before we begin, let us first affirm a very important question: we do not discuss annotations that run processing at runtime (runtime) through the reflection mechanism, but rather on annotations that are processed at compile time (Compile. The annotation processor is a tool that is used in Javac to scan and process annotations at compile time. You can register your own annotation processor for specific annotations.

An annotated note processor that takes Java code (or compiled bytecode) as input, generating files (usually. java files) as output. Java code can be generated, and the generated Java code is in the generated. java file, so you cannot modify a Java class that already exists, such as adding a method to an existing class. These generated Java files are javac compiled in the same way as other normal, manually written Java source code.

Virtual Processor Abstractprocessor

Let's look at the processor's API first. Each processor is inherited from the Abstractprocessor, as follows:

public    Class Myprocessor extends Abstractprocessor {@Override public synchronized void init (Processingenvironment env) {}     @Override public Boolean process (SET<? extends typeelement> annoations, roundenvironment env) {} @Override Public set<string> Getsupportedannotationtypes () {} @Override public sourceversion getsupportedsourcevers Ion () {}} 
    • init (processingenvironment env): Each annotation processor class must have an empty constructor . However, there is a special init () method, which is called by the annotation processing tool and enters the processingenviroment parameter. Processingenviroment offers many useful tools such as elements,types and filer.
    • process (set<? extends typeelement> Annotations, Roundenvironment env): This corresponds to the main function of each processor main (). Write code to scan, evaluate, and process annotations here, as well as generate Java files. Input parameter roundenviroment lets you query out annotated elements that contain specific annotations.
    • getsupportedannotationtypes (): Must be specified here, which annotation the annotation processor is registered to. Note that its return value is a collection of strings containing the legal full name of the type of annotations the processor wants to process. In other words, here you define which annotations your annotation processor is registered to.
    • getsupportedsourceversion (): Used to specify the Java version you are using. Usually return here sourceversion.latestsupported (). However, if there are enough reasons to support Java 6 only, you can return to Sourceversion.release_6. It is recommended to use the former.

Give a simple example

Automatically generate a bean's structure file

Put public class Student {public string stu_name;public string stu_id;public int stu_age;} Convert to {class: "Com.robert.processor.Student", fields   :   {    stu_name: "java.lang.String",    stu_id: " Java.lang.String ",  stu_age:" Java.lang.Integer "}  
First DECLARE annotations

Package Com.robert.processor;import Java.lang.annotation.elementtype;import Java.lang.annotation.retention;import Java.lang.annotation.retentionpolicy;import Java.lang.annotation.Target; @Target ({Elementtype.field, Elementtype.type}) @Retention (retentionpolicy.class) public @interface Serialize {}
Add annotations to the student class
@Serialize
public class Student

Define your own parser

Package Com.robert.processor;import Java.io.file;import Java.io.filewriter;import java.io.ioexception;import Java.util.arraylist;import java.util.hashmap;import java.util.hashset;import Java.util.list;import java.util.Map; Import Java.util.set;import Javax.annotation.processing.abstractprocessor;import Javax.annotation.processing.processingenvironment;import Javax.annotation.processing.roundenvironment;import Javax.lang.model.element.element;import Javax.lang.model.element.elementkind;import Javax.lang.model.element.typeelement;import Javax.lang.model.element.variableelement;import Javax.lang.model.util.elementfilter;import Javax.lang.model.util.elements;public class MyProcessor extends Abstractprocessor {///element operation elements elementutils; @Overridepublic synchronized void init (processingenvironment processingenv) {super.init (processingenv); elementutils = Processingenv.getelementutils ();} @Overridepublic Boolean process (set<? extends typeelement> annotations, roundenvironment RoundenV) {//Obtain the element set&lt by the annotation declaration;? extends element> Elememts = Roundenv.getelementsannotatedwith (Serialize.class); Typeelement classelement = null;//declares the class element list<variableelement> fields = null;//declares a list of member variables to hold//store both map<string, list<variableelement>> maps = new hashmap<string, list<variableelement>> ();//Traverse for (Element ele: ELEMEMTS) {//Determines whether the element is a class if (ele.getkind () = = Elementkind.class) {classelement = (typeelement) ele;maps.put ( Classelement.getqualifiedname (). toString (), fields = new arraylist<variableelement> ());} else if (ele.getkind () = = Elementkind.field)//Determines whether the element is a member variable {variableelement Varele = (variableelement) ele;//Gets the element encapsulation type T Ypeelement enclosingelement = (typeelement) varele.getenclosingelement ();//get keystring key = Enclosingelement.getqualifiedname (). toString (); fields = Maps.get (key), if (n = null) {maps.put (key, fields = new Arraylist<variableelement> ());} Fields.Add (Varele);}} For (String Key:maps.keySet ()) {if (Maps.get (key). Size ()= = 0) {typeelement typeelement = elementutils.gettypeelement (key); list<? Extends element> allmembers = elementutils.getallmembers (typeelement); if (allmembers.size () > 0) {maps.get (key). AddAll (Elementfilter.fieldsin (AllMembers));}} Generatefile (maps); return true;} private void Generatefile (map<string, list<variableelement>> maps) {file Dir = new File ( MyProcessor.class.getResource ("/"). GetPath ()); if (!dir.exists ()) dir.mkdirs ();//Traverse Mapfor (String key:maps.keySet () ) {//create file filename = ' new file ' (dir, key.replaceall ("\ \", "_") + ". txt"); try {/** * Write file contents */filewriter fw = new FileWrite R (file), Fw.append ("{"). Append ("Class:"). Append ("\" "+ key +" \ "). Append (", \ n "); Fw.append (" fields:\n {\ n "); list<variableelement> fields = Maps.get (key), for (int i = 0; i < fields.size (); i++) {variableelement field = Fie Lds.get (i); Fw.append (""). Append (Field.getsimplename ()). Append (":"). Append ("\" + Field.astype (). toString () + "\" ") if (I < fields.size ()-1) {Fw.append (","); Fw.append (" \ n ");}} Fw.append ("\ n}\n"); Fw.append ("}"); Fw.flush (); Fw.close ();} catch (IOException e) {e.printstacktrace ();}}} @Overridepublic set<string> getsupportedannotationtypes () {set<string> Set = Super.getsupportedannotationtypes (); if (set = = null) {set = new hashset<> ();} Set.add ("Com.robert.processor.Serialize"); return set;}}

The butterknife that we often use is a good framework for using abstractprocessor

Butter Knife is an Android view field and method binding that uses annotation processing to generate boilerplate code. Detailed instructions later.


Welcome to scan QR Code, follow the personal public number




Java compile-time annotations automatically generate code

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.