| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| |
| = Suporte aos Processadores de Anotação no NetBeans IDE, Parte II: Utilizando Processadores Próprios de Anotação Personalizada no IDE |
| :jbake-type: tutorial |
| :jbake-tags: tutorials |
| :jbake-status: published |
| :icons: font |
| :syntax: true |
| :source-highlighter: pygments |
| :toc: left |
| :toc-title: |
| :description: Suporte aos Processadores de Anotação no NetBeans IDE, Parte II: Utilizando Processadores Próprios de Anotação Personalizada no IDE - Apache NetBeans |
| :keywords: Apache NetBeans, Tutorials, Suporte aos Processadores de Anotação no NetBeans IDE, Parte II: Utilizando Processadores Próprios de Anotação Personalizada no IDE |
| |
| _Contribuição de Jesse Glick, redigido e mantido por Irina Filippova _ |
| |
| |
| * *Utilizando Processadores Próprios de Anotação Personalizada no IDE* |
| |
| image::../../../images_www/articles/71/netbeans-stamp-71-72-73.png[title="O conteúdo desta página se aplica ao NetBeans IDE 7.0, 7.1, 7.2 e 7.3"] |
| |
| Nesta seção do tutorial, você aprenderá a adicionar um processador de anotação personalizado de redação própria a um projeto no IDE. Este tutorial não ensina como criar um processador de anotação. Ele explica como adicioná-lo a um projeto NetBeans IDE. |
| |
| A aplicação de amostra usada nesta seção foi criada por Jesse Glick e publicada como uma link:http://wiki.netbeans.org/FaqApt[+entrada de FAQ+] das releases anteriores do IDE. |
| |
| O processador de anotação usado como exemplo gera uma classe principal da classe anotada. A classe principal gerada também contém um método chamado usando a classe anotada. Siga as instruções abaixo sobre como criar e adicionar um processador personalizado de anotação em um projeto do IDE. |
| |
| *Para concluir este tutorial, você precisa dos seguintes recursos e softwares.* |
| |
| |=== |
| |Software ou Recurso |Versão Necessária |
| |
| |link:https://netbeans.org/downloads/index.html[+NetBeans IDE+] |7.0, 7.1, 7.2, 7.3 |
| |
| |link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+JDK (Java Development Kit)+] |versão 6 ou 7 |
| |
| |link:http://code.google.com/p/projectlombok/downloads/list[+lombok.jar+] |v1.12.4 ou mais recente |
| |=== |
| |
| |
| == Definindo uma Anotação e Criando um Processador de Anotação |
| |
| Neste exercício, você criará um projeto de biblioteca de classes. |
| |
| 1. Escolha Arquivo > Novo Projeto e selecione o tipo de projeto de Bibliotecas de Classes Java na categoria Java. Clique em Próximo. |
| 2. Digite * ``AnnProcessor`` * como Nome do Projeto e especifique um local para o projeto. Clique em Finalizar. |
| |
| Quando você clica em Finalizar, o IDE cria o projeto de biblioteca de classes e lista o projeto na janela Projetos. |
| |
| |
| [start=3] |
| . Clique com o botão direito do mouse no nó do projeto AnnProcessor na janela Projetos e escolha Propriedades. |
| |
| [start=4] |
| . Na categoria Códigos-fonte, confirme se JDK 6 ou JDK 7 está especificado como o formato de código-fonte/binário. |
| |
| [start=5] |
| . Selecione a guia Bibliotecas e confirme se a plataforma Java está definida como JDK 1.6 ou JDK 1.7. Clique em OK para fechar a janela Propriedades do Projeto. |
| |
| Neste exercício, você criará dois pacotes Java e uma classe Java em cada um destes pacotes. |
| |
| 1. Clique com o botão direito do mouse no nó Pacotes de Código-fonte sob o nó do projeto AnnProcessor e escolha Novo > Pacote Java. |
| 2. Digite * ``ann`` * como Nome do Pacote e clique em Finalizar para criar o novo pacote Java. |
| 3. Repita as duas etapas anteriores para criar um pacote Java chamado * ``proc`` *. |
| |
| Após ter criado os dois pacotes Java, a estrutura do projeto deverá ser similar à seguinte imagem. |
| |
| image::images/packages.png[title="A estrutura do projeto para o processador de anotação."] |
| |
| [start=4] |
| . Clique com o botão direito do mouse no pacote Java ``ann`` e selecione Nova > Classe Java. |
| |
| [start=5] |
| . Digite * ``Handleable`` * para o nome da classe. Clique em Finalizar. |
| |
| [start=6] |
| . Modifique o novo arquivo ``Handleable.java`` para fazer as alterações a seguir. Salve o arquivo. |
| |
| [source,java] |
| ---- |
| |
| package ann; |
| |
| public *@interface* Handleable { |
| |
| } |
| ---- |
| |
| É assim que as anotações são declaradas, de forma muito similar a uma declaração de interface. A diferença é que a palavra-chave ``interface`` precisa ser precedida por um sinal ``at`` (@). Essa anotação é denominada ``Handleable`` . |
| |
| *Informações Adicionais.* Nas declarações de anotação, você também pode especificar parâmetros adicionais, por exemplo, quais tipos de elementos podem ser anotados, por exemplo, classes ou métodos. Você fazer isso adicionando ``@Target(value = {ElementType.TYPE})`` para classes e ``@Target(value = {ElementType.METHOD}).`` Isso, a declaração de anotação torna-se anotada com _meta-anotações_. |
| |
| Agora precisamos adicionar um código para que o processador de anotação processe a anotação ``Handleable`` . |
| |
| |
| [start=7] |
| . Clique com o botão direito do mouse no pacote * ``proc`` * e selecione Nova > Classe Java. |
| |
| [start=8] |
| . Digite * ``HandleableProcessor`` * para o Nome da Classe. Clique em Finalizar. |
| |
| [start=9] |
| . Modifique a classe ``HandleableProcessor.java`` para adicionar o código a seguir. Salve as alterações. |
| |
| *Observação.* O valor de ``@SupportedSourceVersion`` (em *negrito*) dependerá da versão do JDK que você está usando e será ``(SourceVersion.RELEASE_7)`` ou ``(SourceVersion.RELEASE_6)`` . |
| |
| |
| [source,java] |
| ---- |
| |
| package proc; |
| |
| import ann.Handleable; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.io.Writer; |
| import java.util.Set; |
| import javax.annotation.processing.AbstractProcessor; |
| import javax.annotation.processing.RoundEnvironment; |
| import javax.annotation.processing.SupportedAnnotationTypes; |
| import javax.annotation.processing.SupportedSourceVersion; |
| import javax.lang.model.SourceVersion; |
| import javax.lang.model.element.Element; |
| import javax.lang.model.element.ElementKind; |
| import javax.lang.model.element.TypeElement; |
| import javax.lang.model.type.TypeMirror; |
| import javax.tools.Diagnostic; |
| import javax.tools.JavaFileObject; |
| |
| @SupportedAnnotationTypes("ann.Handleable") |
| @SupportedSourceVersion(*SourceVersion.RELEASE_7*) |
| public class HandleableProcessor extends AbstractProcessor { |
| |
| /** public for ServiceLoader */ |
| public HandleableProcessor() { |
| } |
| |
| public boolean process(Set<? extends TypeElement> annotations, |
| RoundEnvironment roundEnv) { |
| for (Element e : roundEnv.getElementsAnnotatedWith(Handleable.class)) { |
| if (e.getKind() != ElementKind.FIELD) { |
| processingEnv.getMessager().printMessage( |
| Diagnostic.Kind.WARNING, |
| "Not a field", e); |
| continue; |
| } |
| String name = capitalize(e.getSimpleName().toString()); |
| TypeElement clazz = (TypeElement) e.getEnclosingElement(); |
| try { |
| JavaFileObject f = processingEnv.getFiler(). |
| createSourceFile(clazz.getQualifiedName() + "Extras"); |
| processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, |
| "Creating " + f.toUri()); |
| Writer w = f.openWriter(); |
| try { |
| PrintWriter pw = new PrintWriter(w); |
| pw.println("package " |
| + clazz.getEnclosingElement().getSimpleName() + ";"); |
| pw.println("public abstract class " |
| + clazz.getSimpleName() + "Extras {"); |
| pw.println(" protected " + clazz.getSimpleName() |
| + "Extras() {}"); |
| TypeMirror type = e.asType(); |
| pw.println(" /** Handle something. */"); |
| pw.println(" protected final void handle" + name |
| + "(" + type + " value) {"); |
| pw.println(" System.out.println(value);"); |
| pw.println(" }"); |
| pw.println("}"); |
| pw.flush(); |
| } finally { |
| w.close(); |
| } |
| } catch (IOException x) { |
| processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, |
| x.toString()); |
| } |
| } |
| return true; |
| } |
| |
| private static String capitalize(String name) { |
| char[] c = name.toCharArray(); |
| c[0] = Character.toUpperCase(c[0]); |
| return new String(c); |
| } |
| } |
| ---- |
| |
| Vamos examinar mais de perto as partes principais que compõem o código para o processador de anotações (observe que, por conveniência, somente partes do código são fornecidas). |
| |
| Primeiro, você especifica os tipos de anotações que o processador de anotações suporta (usando ``@SupportedAnnotationTypes`` ) e a versão dos arquivos de código-fonte que são suportados (usando ``@SupportedSourceVersion`` ); nesse caso, a versão é JDK 6: |
| |
| |
| [source,java] |
| ---- |
| |
| @SupportedAnnotationTypes("ann.Handleable") |
| @SupportedSourceVersion(SourceVersion.RELEASE_6) |
| ---- |
| |
| A seguir, declare uma classe pública para o processador que estenda a classe ``AbstractProcessor`` do pacote ``javax.annotation.processing`` . ``AbstractProcessor`` é a superclasse padrão para processadores de anotação concretos, que contém os métodos necessários para processar anotações. |
| |
| |
| [source,java] |
| ---- |
| |
| public class HandleableProcessor extends AbstractProcessor { |
| ... |
| } |
| ---- |
| |
| Você agora precisa fornecer um construtor público para a classe. |
| |
| |
| [source,java] |
| ---- |
| |
| public class HandleableProcessor extends AbstractProcessor { |
| * public HandleableProcessor() { |
| }* |
| ... |
| |
| } |
| ---- |
| |
| A seguir, chame o método de ``process`` () da classe ``AbstractProcessor`` principal. Por meio deste método, as anotações disponíveis para processamento são fornecidas. Além disso, este método contém informações sobre o ciclo de processamento. |
| |
| |
| [source,java] |
| ---- |
| |
| public class HandleableProcessor extends AbstractProcessor {* |
| *... |
| * public boolean process(Set<? extends TypeElement> annotations, |
| RoundEnvironment roundEnv) { |
| ... |
| } |
| * |
| } |
| ---- |
| |
| A lógica do processador de anotação está contida dentro do método ``process()`` da classe ``AbstractProcessor`` . Observe que, por meio de ``AbstractProcessor`` , você também acessa a interface ``ProcessingEnvironment`` , que permite que os processadores de anotação usem diversos recursos úteis, como um Filer (um handler de arquivamento que permite que os processadores de anotação criem novos arquivos) e um Messager (um meio pelo qual os processadores de anotação reportam erros). |
| |
| |
| [source,java] |
| ---- |
| |
| public class HandleableProcessor extends AbstractProcessor {* |
| *... |
| public boolean process(Set<? extends TypeElement> annotations, |
| RoundEnvironment roundEnv) {//For each element annotated with the Handleable annotation |
| *for (Element e : roundEnv.getElementsAnnotatedWith(Handleable.class)) { |
| |
| *//Check if the type of the annotated element is not a field. If yes, return a warning*. |
| if (e.getKind() != ElementKind.FIELD) { |
| processingEnv.getMessager().printMessage( |
| Diagnostic.Kind.WARNING, |
| "Not a field", e); |
| continue; |
| } |
| *//Define the following variables: name and clazz*.** |
| String name = capitalize(e.getSimpleName().toString()); |
| TypeElement clazz = (TypeElement) e.getEnclosingElement(); |
| *//Generate a source file with a specified class name. * |
| try { |
| JavaFileObject f = processingEnv.getFiler(). |
| createSourceFile(clazz.getQualifiedName() + "Extras"); |
| processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, |
| "Creating " + f.toUri()); |
| Writer w = f.openWriter(); |
| *//Add the content to the newly generated file*. |
| try { |
| PrintWriter pw = new PrintWriter(w); |
| pw.println("package " |
| + clazz.getEnclosingElement().getSimpleName() + ";"); |
| pw.println("public abstract class " |
| + clazz.getSimpleName() + "Extras {"); |
| pw.println(" protected " + clazz.getSimpleName() |
| + "Extras() {}"); |
| TypeMirror type = e.asType(); |
| pw.println(" /** Handle something. */"); |
| pw.println(" protected final void handle" + name |
| + "(" + type + " value) {"); |
| pw.println(" System.out.println(value);"); |
| pw.println(" }"); |
| pw.println("}"); |
| pw.flush(); |
| } finally { |
| w.close(); |
| } |
| } catch (IOException x) { |
| processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, |
| x.toString()); |
| } |
| }*return true; |
| * }* |
| ... |
| } |
| ---- |
| |
| O último bloco neste código declara o método ``capitalize`` que é usado para colocar em maiúscula o nome do elemento anotado. |
| |
| |
| [source,java] |
| ---- |
| |
| public class HandleableProcessor extends AbstractProcessor {* |
| *...* |
| |
| private static String capitalize(String name) { |
| char[] c = name.toCharArray(); |
| c[0] = Character.toUpperCase(c[0]); |
| return new String(c); |
| } |
| *} |
| ---- |
| |
| [start=10] |
| . Compile o projeto clicando com o botão direito do mouse no projeto ``AnnProcessor`` e escolhendo Compilar. |
| |
| |
| == Usando o processador de anotação no IDE |
| |
| Nesta seção, você criará um projeto da Aplicação Java no qual o processador de anotações será usado. |
| |
| 1. Escolha Arquivo > Novo Projeto e selecione o tipo de projeto da Aplicação Java na categoria Java. Clique em Próximo. |
| 2. Na página Nome e Localização, digite * ``Demo`` * como Nome do Projeto e especifique o local do projeto. |
| 3. Digite * ``demo.Main`` * no campo Criar Classe Principal. Clique em Finalizar. |
| image::images/demo-project-wizard.png[title="Criando projeto de Demonstração no assistente de Novo Projeto."] |
| |
| [start=4] |
| . Abra a janela Propriedades do Projeto e confirme se JDK 6 ou JDK 7 está selecionado como o formato de código-fonte/binário no painel Códigos-fonte e se a plataforma Java está definida como JDK 1.6 ou JDK 1.7 no painel Bibliotecas. |
| |
| [start=5] |
| . Modifique a classe ``Main.java`` para adicionar o código a seguir. Salve as alterações. |
| |
| [source,java] |
| ---- |
| |
| package demo; |
| |
| *import ann.Handleable;* |
| |
| public class Main *extends MainExtras* { |
| |
| *@Handleable |
| private String stuff;* |
| |
| *public static void main(String[] args) { |
| new Main().handleStuff("hello"); |
| }* |
| } |
| ---- |
| |
| O código contém os seguintes elementos: |
| |
| * instrução de importação para o processador personalizado de anotação ``ann.Handleable`` |
| * a classe pública ``Main`` que estende a classe ``MainExtras`` ( ``MainExtras`` deve ser gerada por seu processador de anotação durante a compilação) |
| * um campo privado denominado ``stuff`` que é anotado com a anotação ``@Handleable`` |
| * o método ``main`` que chama o método ``handleStuff`` , declarado na classe ``MainExtras`` automaticamente gerada |
| |
| Em nosso exemplo simples, o método ``handleStuff`` somente imprime o valor atual. Você pode modificar este método para executar outras tarefas. |
| |
| Após salvar o código ``Main.java`` , você verá que o IDE relata diversos erros de compilação. Isso acontece porque o processador de anotação ainda não foi adicionado no projeto. |
| |
| |
| [start=6] |
| . Clique com o botão direito do mouse no nó do projeto ``Demo`` , na janela Projetos, escolha Propriedades e, em seguida, selecione a categoria Bibliotecas na janela Propriedades do Projeto. |
| |
| [start=7] |
| . Na guia Compilar, clique em Adicionar Projeto e localize o projeto ``AnnProcessor`` . |
| image::images/demo-properties-compile.png[title="Guia Compilar na categoria Bibliotecas da janela Propriedades do projeto"] |
| |
| A guia Compilar corresponde a opção ``-classpath`` do link:http://download.oracle.com/javase/6/docs/technotes/tools/windows/javac.html#options[+compilador Java+]. Como o processador de anotação é um arquivo JAR único que contém a definição da anotação e o processador de anotação, ele deve ser adicionado na classpath do projeto, que é a guia Compilar. |
| |
| |
| [start=8] |
| . Selecione a categoria Compilação na janela Propriedades do Projeto e marque as caixas de seleção Ativar Processamento de Anotações e Ativar Processamento de Anotações no Editor. |
| |
| [start=9] |
| . Especifique o processador de anotações a ser executado clicando no botão Adicionar ao lado da área de texto Processadores de Anotações e digitando * ``proc.HandleableProcessor`` * no campo FQN do Processador de Anotações. |
| image::images/demo-processor-fqn.png[title="Caixa de diálogo FQN do Processador de Anotação"] |
| |
| A categoria Compilação na janela Propriedades do Projeto deve ser semelhante à imagem a seguir. |
| |
| image::images/demo-properties-compiling.png[title="Categoria compilação na janela Propriedades do projeto"] |
| |
| [start=10] |
| . Clique em OK na janela Propriedades. |
| |
| *Observação.* No arquivo ``Main.java`` talvez você ainda veja os erros de compilação. Isso é porque o IDE ainda não pode localizar o arquivo ``MainExtras.java`` que declara o método ``handleStuff`` . O arquivo ``MainExtras.java`` será gerado após você desenvolver o projeto Demo pela primeira vez. Se Compilar ao Salvar estiver ativado para seu projeto, o IDE compilou o projeto quando você salvou o ``Main.java`` . |
| |
| |
| [start=11] |
| . Clique com o botão direito do mouse no projeto Demo e escolha Construir. |
| |
| Após construir o projeto, se você examinar os projetos na janela Projetos, poderá agora ver um novo nó ``Códigos-fonte Gerados`` com o arquivo ``demo/MainExtras.java`` . |
| |
| image::images/demo-generated-sources.png[title="Janela Projetos com Origens Geradas"] |
| |
| Caso você revise o conteúdo do arquivo ``MainExtras.java`` gerado, verá que o processador de anotações gerou a classe ``MainExtras`` com o método ``handleStuff`` . O método ``handleStuff`` é aquele chamado a partir do arquivo ``Main.java`` anotado. |
| |
| |
| [source,java] |
| ---- |
| |
| package demo; |
| public abstract class MainExtras { |
| protected MainExtras() {} |
| /** Handle something. */ |
| protected final void handleStuff(java.lang.String value) { |
| System.out.println(value); |
| } |
| } |
| ---- |
| |
| [start=12] |
| . Clique com o botão direito do mouse no projeto Demonstração e escolha Executar. |
| |
| Quando você clicar em Executar, deverá ver o seguinte na janela Saída. O projeto Demonstração é compilado e imprime a mensagem. |
| |
| image::images/demo-run.png[title="Janela Projetos com Origens Geradas"] |
| link:/about/contact_form.html?to=3&subject=Feedback:%20Using%20the%20Annotation%20Processors%20Support%20in%20NetBeans%20IDE[+Enviar Feedback neste Tutorial+] |
| |
| |
| == Consulte Também |
| |
| Consulte os seguintes recursos para obter mais informações sobre anotações em aplicações Java: |
| |
| * Documentação Java SE - link:http://download.oracle.com/javase/6/docs/technotes/guides/language/annotations.html[+Anotações+] |
| * Tutorial Java SE - link:http://download.oracle.com/javase/tutorial/java/javaOO/annotations.html[+Anotações+] |
| * link:http://download.oracle.com/javase/6/docs/technotes/tools/windows/javac.html#processing[+Compilador do Java: Opções de Processamento de Anotação+] |
| * link:http://blogs.oracle.com/darcy/[+Weblog de Joseph D. Darcy's Weblog+] - dicas úteis sobre a especificação JSR-269 |