Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Anotações Java Além da Reflexão

Anotações Java Além da Reflexão

Wellington Costa

July 14, 2018
Tweet

More Decks by Wellington Costa

Other Decks in Technology

Transcript

  1. Wellington Costa Pereira • +4 anos de experiência • Mestrando

    em Ciências da Computação (UECE) • Programar é vida! • Open source <3 • Compartilhar conhecimento <3 Github: https://github.com/WellingtonCosta Linkedin: https://www.linkedin.com/in/wellingtoncosta128 Email: [email protected]
  2. Anotações Introduzida na versão 5 do Java, as anotações, ou

    Annotations, são uma forma de representar metadados que podem vir a serem interpretados por um compilador, visando realizar alguma ação a partir desses metadados. As annotations também podem servir como uma forma para substituição das tradicionais configurações baseadas em XML ou até mesmo para geração de arquivos, muitas vezes arquivos de código-fonte.
  3. Lombok @ToString @EqualsAndHashCode public class Pessoa { @Getter @Setter private

    Long id; @Getter @Setter private String nome; @Getter @Setter private String email; @Getter @Setter private String telefone; }
  4. JPA @Entity @Table(name = "tb_pessoa") public class Pessoa { @Id

    private Long id; @Column private String nome; @Column private String email; @Column private String telefone; }
  5. Butter Knife public class PessoaActivity extends Activity { @BindView(R.id.nome) TextView

    nome; @BindView(R.id.email) TextView email; @BindView(R.id.telefone) TextView telefone; @Override protected void onCreate(Bundle savedInstance) { // … ButterKnife.inject(this); } }
  6. Java 5 • JSR 14: Generics • JSR 175: Annotations

    • JSR 201: ◦ Autoboxing / Unboxing ◦ Enumerations ◦ Static Imports ◦ Enhanced For Loops • apt command-line tool • Dentre outras funcionalidades bacanas!
  7. JSR 269 • 6 meses após o lançamento do Java

    5 • “Pluggable Annotation Processing API” • Google, Oracle, dentre outras organizações patrocinaram • Simplificar e padronizar o processamento de anotações • Agora o apt faz parte do javac
  8. interface Processor { Set<String> getSupportedOptions(); Set<String> getSupportedAnnotationTypes(); SourceVersion getSupportedSourceVersion(); void

    init(ProcesssingEnvironment processingEnv); boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env); Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText); }
  9. interface Processor { Set<String> getSupportedOptions(); Set<String> getSupportedAnnotationTypes(); SourceVersion getSupportedSourceVersion(); void

    init(ProcesssingEnvironment processingEnv); boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env); Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText); }
  10. interface ProcessingEnvironment { Map<String, String> getOptions(); SourceVersion getSourceVersion(); Locale getLocale();

    Messager getMessager(); Filer getFiler(); Elements getElementUtils(); Types getTypeUtils(); }
  11. interface ProcessingEnvironment { Map<String, String> getOptions(); SourceVersion getSourceVersion(); Locale getLocale();

    Messager getMessager(); Filer getFiler(); Elements getElementUtils(); Types getTypeUtils(); }
  12. Elements public class HelloClass implements Runnable { private final String

    name; public HelloClass(String name) { this.name = name; } @Override public void run() { System.out.println(“Hello, ” + name); } }
  13. public class HelloClass implements Runnable { TypeElement private final String

    name; public HelloClass(String name) { this.name = name; } @Override public void run() { System.out.println(“Hello, ” + name); } } Elements
  14. public class HelloClass implements Runnable { TypeElement private final String

    name; VariableElement public HelloClass(String name) { this.name = name; } @Override public void run() { System.out.println(“Hello, ” + name); } } Elements
  15. public class HelloClass implements Runnable { TypeElement private final String

    name; VariableElement public HelloClass(String name) { this.name = name; ExecutableElement } @Override public void run() { System.out.println(“Hello, ” + name); } } Elements
  16. public class HelloClass implements Runnable { TypeElement private final String

    name; VariableElement public HelloClass(String name) { this.name = name; ExecutableElement } @Override public void run() { System.out.println(“Hello, ” + name); ExecutableElement } } Elements
  17. public class HelloClass implements Runnable { private final String name;

    public HelloClass(String name) { this.name = name; } @Override public void run() { System.out.println(“Hello, ” + name); } } Types
  18. public class HelloClass implements Runnable { private final String name;

    public HelloClass(String name) { this.name = name; } @Override public void run() { System.out.println(“Hello, ” + name); } } Types
  19. public class HelloClass implements Runnable { private final String name;

    public HelloClass(String name) { this.name = name; } @Override public void run() { System.out.println(“Hello, ” + name); } } Types
  20. public class HelloClass implements Runnable { private final String name;

    public HelloClass(String name) { this.name = name; } @Override public void run() { System.out.println(“Hello, ” + name); } } Types
  21. public class HelloClass implements Runnable { private final String name;

    public HelloClass(String name) { this.name = name; } @Override public void run() { System.out.println(“Hello, ” + name); } } Types
  22. public class HelloClass implements Runnable { private final String name;

    public HelloClass(String name) { this.name = name; } @Override public void run() { System.out.println(“Hello, ” + name); } } Types
  23. public class HelloWorldProcessor extends AbstractProcessor { @Override public SourceVersion getSupportedSourceVersion()

    { return SourceVersion.latestSupported(); } @Override public Set<String> getSupportedAnnotationTypes() { return Collections.singleton(HelloWorld.class.getName()); } }
  24. public class HelloWorldProcessor extends AbstractProcessor { @Override public SourceVersion getSupportedSourceVersion()

    { return SourceVersion.latestSupported(); } @Override public Set<String> getSupportedAnnotationTypes() { return Collections.singleton(HelloWorld.class.getName()); } @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env) { } }
  25. public class HelloWorldProcessor extends AbstractProcessor { // . . .

    @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env) { } }
  26. public class HelloWorldProcessor extends AbstractProcessor { // . . .

    @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env) { Set<? extends Element> elements = env.getElementsAnnotatedWith(HelloWorld.class); } }
  27. public class HelloWorldProcessor extends AbstractProcessor { // . . .

    @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env) { Set<? extends Element> elements = env.getElementsAnnotatedWith(HelloWorld.class); for(Element element : elements) { System.out.println(element); } } }
  28. public class HelloWorldProcessor extends AbstractProcessor { // . . .

    @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env) { Set<? extends Element> elements = env.getElementsAnnotatedWith(HelloWorld.class); for(Element element : elements) { System.out.println(element); } return false; } }
  29. public class HelloWorldProcessor extends AbstractProcessor { @Override public SourceVersion getSupportedSourceVersion()

    { return SourceVersion.latestSupported(); } @Override public Set<String> getSupportedAnnotationTypes() { return Collections.singleton(HelloWorld.class.getName()); } @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env) { Set<? extends Element> elements = env.getElementsAnnotatedWith(HelloWorld.class); for(Element element : elements) { System.out.println(element); } return false; } }
  30. • Acontece automaticamente quando javac é executado • ServiceLoader se

    encarrega de encontrar e instanciar os Processor Execução
  31. • META-INF/services • Nome do arquivo ◦ javax.annotation.processing.Processor • Cada

    linha do arquivo deve ter o nome completo de cada Processor ◦ com.example.HelloWorldProcessor ServiceLoader
  32. • Acontece em duas etapas • A primeira etapa processa

    os elementos anotados ◦ Novos arquivos de código fonte podem ser gerados ◦ Os arquivos compilados tem como saída seus bytecodes • A segunda etapa acontece para verificar se novos arquivos gerados ◦ Os eventuais arquivos gerados são compilados e tem como saída os arquivos bytecode Processing Rounds
  33. public class HelloWorldProcessor extends AbstractProcessor { // . . .

    @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env) { Set<? extends Element> elements = env.getElementsAnnotatedWith(HelloWorld.class); for(Element element : elements) { // Analisar os atributos de ‘element’ // Gerar código a partir desses atributos } return false; } }
  34. @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env)

    { List<ClassInfo> classesInfo = parseHelloWorldAnnotation(env); return false; }
  35. @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env)

    { List<ClassInfo> classesInfo = parseHelloWorldAnnotation(env); return false; } List<ClassInfo> parseHelloWorldAnnotation(RoundEnvironment env) { // . . . }
  36. @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env)

    { List<ClassInfo> classesInfo = parseHelloWorldAnnotation(env); for(ClassInfo classInfo : classesInfo) { generateHelloWorldCode(classInfo); } return false; } List<ClassInfo> parseHelloWorldAnnotation(RoundEnvironment env) { // . . . }
  37. @Override public boolean process( Set<? extends TypeElement> annotations, RoundEnvironment env)

    { List<ClassInfo> classesInfo = parseHelloWorldAnnotation(env); for(ClassInfo classInfo : classesInfo) { generateHelloWorldCode(classInfo); } return false; } List<ClassInfo> parseHelloWorldAnnotation(RoundEnvironment env) { // . . . } void generateHelloWorldCode(ClassInfo classInfo) { // . . . }
  38. • Lembram? META-INF/services/javax.annotation.processing.Processor • AutoService gera esses arquivos através de

    anotações! Google Auto Service public class HelloWorldProcessor extends AbstractProcessor { // . . . }
  39. • Lembram? META-INF/services/javax.annotation.processing.Processor • AutoService gera esses arquivos através de

    anotações! Google Auto Service @AutoService(Processor.class) public class HelloWorldProcessor extends AbstractProcessor { // . . . }