java annotation processing: a beginner walkthrough

50
Java Annotation Processing A Beginner Walkthrough Mahfuz Islam Bhuiyan Software Engineer, Genweb2

Upload: mahfuz-islam-bhuiyan

Post on 06-Jan-2017

528 views

Category:

Software


2 download

TRANSCRIPT

Page 1: Java Annotation Processing: A Beginner Walkthrough

Java Annotation ProcessingA Beginner Walkthrough

Mahfuz Islam Bhuiyan

Software Engineer, Genweb2

Page 2: Java Annotation Processing: A Beginner Walkthrough

What’s Annotation?● Provide meta-data for Java code

● Can describe usage of an element, e.g. @Deprecated

● Can describe the nature of an element, e.g. @WebService

● and many more

Page 3: Java Annotation Processing: A Beginner Walkthrough

Built-in Java Annotations@Deprecated

@Override

@SuppressWarning

Page 4: Java Annotation Processing: A Beginner Walkthrough

Custom Annotationpublic @interface MyAnnotation { // @interface tells Java that it’s a custom annotation

String value();

String name(); int age(); String[] newNames();}

Page 5: Java Annotation Processing: A Beginner Walkthrough

Custom Annotation@MyAnnotation( value="Test123456", name=" Oveget ", age=37, newNames={"Rishi", "Farzana"})public class MyClass {

}

Page 6: Java Annotation Processing: A Beginner Walkthrough

Custom Annotationpublic @interface MyAnnotation {

String value() default "";

String name() default " The Sufi ";

int age(); String[] newNames();

}

Page 7: Java Annotation Processing: A Beginner Walkthrough

Annotation Processing Trends● Remove boilerplate

● Inject Source Code

● Validate Fields, Methods, Class etc

Page 8: Java Annotation Processing: A Beginner Walkthrough

Annotation Processing Facts● Part of javac

● Introduced in Java 5

● Run at Compile Time(!)

● Own JVM

● Native Java code

● No Reflection(by default)

Page 9: Java Annotation Processing: A Beginner Walkthrough
Page 10: Java Annotation Processing: A Beginner Walkthrough

Java Reflection● Makes it possible to inspect classes, interfaces, fields and methods at runtime,

without knowing the names of the classes, methods etc. at compile time.

● Can instantiate new objects, invoke methods and get/set field values using

reflection.

Page 11: Java Annotation Processing: A Beginner Walkthrough

Java ReflectionsMethod[] methods = MyObject.class.getMethods();

for(Method method : methods){ System.out.println("method = " + method.getName());}

Page 12: Java Annotation Processing: A Beginner Walkthrough

Java ReflectionsClass aClass = MyObject.classField field = aClass.getField("someField");

MyObject objectInstance = new MyObject();

Object value = field.get(objectInstance);

field.set(objetInstance, value);

Page 13: Java Annotation Processing: A Beginner Walkthrough

@Retention@Retention(RetentionPolicy.RUNTIME) // Allows the annotation to be available at Runtime

@Target({ElementType.METHOD})public @interface MyAnnotation { // Yes, we can apply annotation over another annotation

String value() default "";

}

Page 14: Java Annotation Processing: A Beginner Walkthrough

Annotation Processing Limitations● Generate only new files

● Can’t manipulate already existing files(But byte manipulation possible with

sacrificing debugging capability)

Page 15: Java Annotation Processing: A Beginner Walkthrough

Create Your Own Annotation Processor1. Extends AbstractProcessor

2. Register the processor with javac

Page 16: Java Annotation Processing: A Beginner Walkthrough
Page 17: Java Annotation Processing: A Beginner Walkthrough

Extending Abstract Processorpublic 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 getSupportedSourceVersion() { }

}

Page 18: Java Annotation Processing: A Beginner Walkthrough

Extending Abstract Processor@SupportedSourceVersion(SourceVersion.latestSupported())@SupportedAnnotationTypes({ // Set of full qualified annotation type names })public class MyProcessor extends AbstractProcessor {

@Override public synchronized void init(ProcessingEnvironment env){ }

@Override public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { }}

Page 19: Java Annotation Processing: A Beginner Walkthrough

Extending Abstract Processor@SupportedSourceVersion(SourceVersion.latestSupported())@SupportedAnnotationTypes({ // Set of full qualified annotation type names })public class MyProcessor extends AbstractProcessor {

@Override public synchronized void init(ProcessingEnvironment env){ }

// We need to get our hands dirty with following method @Override public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { }}

Page 20: Java Annotation Processing: A Beginner Walkthrough

Register the Processor1. Create a .jar file with our Annotation Processor Java file

2. Provide a special file called javax.annotation.processing.Processor located in

META-INF/services in your .jar file

3. Within the javax.annotation.processing.Processor , there should be the fully

qualified names of the processors contained in the Jar file(like, com.example.

MyProcessor.class)

Page 21: Java Annotation Processing: A Beginner Walkthrough

So, it’ll look likeMyProcessor.jar

=> com

=> example

=> MyProcessor.class

=> META-INF

=> services

=> javax.annotation.processing.Processor

Page 22: Java Annotation Processing: A Beginner Walkthrough

Validate a Class with Custom Annotation Processor

Page 23: Java Annotation Processing: A Beginner Walkthrough

Annotationimport com.example;

public @interface ConstructorCheck{

}

Page 24: Java Annotation Processing: A Beginner Walkthrough

Annotation Processor@SupportedSourceVersion(SourceVersion.latestSupported())@SupportedAnnotationTypes({"com.example.ConstructorCheck"})}public class MyProcessor extends AbstractProcessor {

@Override public synchronized void init(ProcessingEnvironment env){ }

@Override public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { }}

Page 25: Java Annotation Processing: A Beginner Walkthrough

initProcessingEnvironment processingEnv;

@Overridepublic synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); this.processingEnv = processingEnv;}

Page 26: Java Annotation Processing: A Beginner Walkthrough

ProcessingEnvironment● getElementUtils => Elements

● getTypeUtils => Types

● getFiler => Filer

● getMessager => Messager

Page 27: Java Annotation Processing: A Beginner Walkthrough

Element● Is not a class per se !

● Contains value that can be of Class, Interface etc

Page 28: Java Annotation Processing: A Beginner Walkthrough
Page 29: Java Annotation Processing: A Beginner Walkthrough

Elementpublic class User{ // TypeElement

private String name; // VariableElement

private Person personObj; // VariableElement

public User(){} // ExecutableElement

public boolean isUserHasNID(){ // ExecutableElement /*...*/ }}

Page 30: Java Annotation Processing: A Beginner Walkthrough

TypeMirror● Provide some meta data about Element

● Get to know the class inheritance hierarchy, for instance

Page 31: Java Annotation Processing: A Beginner Walkthrough

process@Overridepublic boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { checkEntityAnnotatedElements(roundEnv); return false; // true if we want to stop processor’s further execution

}

Page 32: Java Annotation Processing: A Beginner Walkthrough

private void checkEntityAnnotatedElements(RoundEnvironment roundEnv) {

Set <? extends Element > entityAnnotated = roundEnv.getElementsAnnotatedWith(CheckConstructor.class);

for (TypeElement typeElement: ElementFilter.typesIn(entityAnnotated)) {

for (ExecutableElement constructor: ElementFilter.constructorsIn(typeElement.getEnclosedElements())) { List <? extends VariableElement > parameters = constructor.getParameters();

if (parameters.isEmpty()) return; } AnnotationMirror entityAnnotation = getAnnotation(typeElement, entityType.type); processingEnv.getMessager().printMessage(Kind.ERROR, "missing no argument constructor", typeElement, entityAnnotation); }}

Page 33: Java Annotation Processing: A Beginner Walkthrough

Automatic Source Code Generating Tool

Page 34: Java Annotation Processing: A Beginner Walkthrough

JavaPoet● JavaPoet is a API for generating java source files.

● It can be useful when doing things such as annotation processing or interacting

with metadata files.

Page 35: Java Annotation Processing: A Beginner Walkthrough

JavaPoetHere goes a plain simple java class

package com.example.helloworld;

public final class HelloWorld {

public static void main(String[] args) { System.out.println("Hello, JavaPoet!"); }}

Page 36: Java Annotation Processing: A Beginner Walkthrough

JavaPoetWith JavaPoet, it’ll look like this.

MethodSpec main = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(void.class).addParameter(String[].class, "args") .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!").build();

TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld") .addModifiers(Modifier.PUBLIC, Modifier.FINAL).addMethod(main).build();

JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld).build();

javaFile.writeTo(System.out)

Page 37: Java Annotation Processing: A Beginner Walkthrough
Page 38: Java Annotation Processing: A Beginner Walkthrough

Some Cool Annotation Based Tools

Page 39: Java Annotation Processing: A Beginner Walkthrough

Project Lombok● Project Lombok greatly reduces the number of lines of boilerplate code

Page 40: Java Annotation Processing: A Beginner Walkthrough
Page 41: Java Annotation Processing: A Beginner Walkthrough

Dagger 2 ● Dagger 2 is a fork from Dagger 1 under heavy development by Google

● Dependency Injection design pattern without the burden of writing the

boilerplate

● No reflection at all

● Achieved 13% performance boost over Dagger 1

Page 42: Java Annotation Processing: A Beginner Walkthrough

Butter Knife● Butter Knife injects views on Android

● Reduce boilerplate codes

● Support Resource and Event binding too

Page 43: Java Annotation Processing: A Beginner Walkthrough

Butter Knifeclass ExampleActivity extends Activity { TextView title, subtitle; EditText inputTitle, inputSubTitle;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity);

title = (TextView)findViewById(R.id.title); subtitle = (TextView)findViewById(R.id.subtitle); inputTitle = (EditText)findViewById(R.id.inputTitle); inputSubtitle = (EditText)findViewById(R.id.inputSubTitle); }}

Page 44: Java Annotation Processing: A Beginner Walkthrough

Butter Knifeclass ExampleActivity extends Activity { @Bind(R.id.title) TextView title; @Bind(R.id.subtitle) TextView subtitle; @Bind(R.id.subtitle) EditText inputTitle; @Bind(R.id.subtitle) EditText inputSubtitle;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.simple_activity); ButterKnife.bind(this); }}

Page 45: Java Annotation Processing: A Beginner Walkthrough
Page 46: Java Annotation Processing: A Beginner Walkthrough
Page 47: Java Annotation Processing: A Beginner Walkthrough
Page 48: Java Annotation Processing: A Beginner Walkthrough
Page 50: Java Annotation Processing: A Beginner Walkthrough

@thankYou