`
xiangxingchina
  • 浏览: 523636 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

注解apt工具示例程序

 
阅读更多

今天按照《Thinking in Java》中使用apt处理注解一节,将书中代码写了一遍,但运行过程中出现了一个问题让我很纳闷,下面先把代码呈上,问题稍后再说。

  程序功能很简单,就是从被注解的类中提取出public方法,然后使用注解处理器生成一个包含这些public方法的接口文件。

具体介绍可以参考原书。

 

ExtractInterface.java——注解定义

Java代码  收藏代码
  1. /** 
  2.  *  
  3.  */  
  4. package net.lazydoggy.annotations.aptdemo;  
  5.   
  6. import java.lang.annotation.ElementType;  
  7. import java.lang.annotation.Retention;  
  8. import java.lang.annotation.RetentionPolicy;  
  9. import java.lang.annotation.Target;  
  10.   
  11. /** 
  12.  * @author hanzhaozhan 
  13.  * 
  14.  */  
  15. @Target(ElementType.TYPE)  
  16. @Retention(RetentionPolicy.SOURCE)  
  17. public @interface ExtractInterface {  
  18.     String value();  
  19. }  

 

Multiplier.java——使用了注解的目标类

Java代码  收藏代码
  1. /** 
  2.  *  
  3.  */  
  4. package net.lazydoggy.annotations.aptdemo;  
  5.   
  6. /** 
  7.  * @author hanzhaozhan 
  8.  *  
  9.  */  
  10. @ExtractInterface("Imultiplier")  
  11. public class Multiplier {  
  12.     public int multiply(int x, int y) {  
  13.         int total = 0;  
  14.         for (int i = 0; i < x; i++) {  
  15.             total = add(total, y);  
  16.         }  
  17.   
  18.         return total;  
  19.     }  
  20.   
  21.     private static int add(int x, int y) {  
  22.         return x + y;  
  23.     }  
  24.       
  25.     public static void main(String[] args) {  
  26.         Multiplier m = new Multiplier();  
  27.         System.out.println("11 * 16 = " + m.multiply(1116));  
  28.     }  
  29. }  

 

InterfaceExtractorProcessor.java——注解处理器类

Java代码  收藏代码
  1. package net.lazydoggy.annotations.aptdemo;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5. import java.util.ArrayList;  
  6.   
  7. import com.sun.mirror.apt.AnnotationProcessor;  
  8. import com.sun.mirror.apt.AnnotationProcessorEnvironment;  
  9. import com.sun.mirror.declaration.MethodDeclaration;  
  10. import com.sun.mirror.declaration.ParameterDeclaration;  
  11. import com.sun.mirror.declaration.TypeDeclaration;  
  12.   
  13. public class InterfaceExtractorProcessor implements AnnotationProcessor {  
  14.     private final AnnotationProcessorEnvironment env;  
  15.     private ArrayList<MethodDeclaration> interfaceMethods = new ArrayList<MethodDeclaration>();  
  16.   
  17.     public InterfaceExtractorProcessor(AnnotationProcessorEnvironment env) {  
  18.         this.env = env;  
  19.     }  
  20.   
  21.     @Override  
  22.     public void process() {  
  23.         for (TypeDeclaration typeDel : env.getSpecifiedTypeDeclarations()) {  
  24.             ExtractInterface annot = typeDel  
  25.                     .getAnnotation(ExtractInterface.class);  
  26.             if (annot == null) {  
  27.                 break;  
  28.             }  
  29.             for (MethodDeclaration m : typeDel.getMethods()) {  
  30.                 if (m.getModifiers().toString().contains("public")  
  31.                         && !(m.getModifiers().toString().contains("static"))) {  
  32.                     interfaceMethods.add(m);  
  33.                 }  
  34.             }  
  35.             if (interfaceMethods.size() > 0) {  
  36.                 try {  
  37.                     PrintWriter writer = env.getFiler().createSourceFile(  
  38.                             annot.value());  
  39.                     writer.println("package "  
  40.                             + typeDel.getPackage().getQualifiedName() + ";");  
  41.                     writer.println("public interface " + annot.value() + " {");  
  42.                     for (MethodDeclaration m : interfaceMethods) {  
  43.                         writer.print("\tpublic ");  
  44.                         writer.print(m.getReturnType() + " ");  
  45.                         writer.print(m.getSimpleName() + "(");  
  46.                         int i = 0;  
  47.                         for (ParameterDeclaration param : m.getParameters()) {  
  48.                             writer.print(param.getType() + " "  
  49.                                     + param.getSimpleName());  
  50.                             if (++i < m.getParameters().size()) {  
  51.                                 writer.print(",");  
  52.                             }  
  53.                         }  
  54.                         writer.println(");");  
  55.                     }  
  56.                     writer.println("}");  
  57.                     writer.close();  
  58.                 } catch (IOException e) {  
  59.                     e.printStackTrace();  
  60.                 }  
  61.   
  62.             }  
  63.         }  
  64.     }  
  65.   
  66. }  

 

InterfaceExtractorProcessorFactory.java——处理器工厂类

Java代码  收藏代码
  1. /** 
  2.  *  
  3.  */  
  4. package net.lazydoggy.annotations.aptdemo;  
  5.   
  6. import java.util.Collection;  
  7. import java.util.Collections;  
  8. import java.util.Set;  
  9.   
  10. import com.sun.mirror.apt.AnnotationProcessor;  
  11. import com.sun.mirror.apt.AnnotationProcessorEnvironment;  
  12. import com.sun.mirror.apt.AnnotationProcessorFactory;  
  13. import com.sun.mirror.declaration.AnnotationTypeDeclaration;  
  14.   
  15. /** 
  16.  * @author hanzhaozhan 
  17.  *  
  18.  */  
  19. public class InterfaceExtractorProcessorFactory implements  
  20.         AnnotationProcessorFactory {  
  21.   
  22.     /* 
  23.      * (non-Javadoc) 
  24.      *  
  25.      * @see 
  26.      * com.sun.mirror.apt.AnnotationProcessorFactory#getProcessorFor(java.util 
  27.      * .Set, com.sun.mirror.apt.AnnotationProcessorEnvironment) 
  28.      */  
  29.     @Override  
  30.     public AnnotationProcessor getProcessorFor(  
  31.             Set<AnnotationTypeDeclaration> atds,  
  32.             AnnotationProcessorEnvironment env) {  
  33.         return new InterfaceExtractorProcessor(env);  
  34.     }  
  35.   
  36.     /* 
  37.      * (non-Javadoc) 
  38.      *  
  39.      * @see 
  40.      * com.sun.mirror.apt.AnnotationProcessorFactory#supportedAnnotationTypes() 
  41.      */  
  42.     @Override  
  43.     public Collection<String> supportedAnnotationTypes() {  
  44.         return Collections  
  45.                 .singleton("net.lazydoggy.annotations.aptdemo.ExtractInterface");  
  46.     }  
  47.   
  48.     /* 
  49.      * (non-Javadoc) 
  50.      *  
  51.      * @see com.sun.mirror.apt.AnnotationProcessorFactory#supportedOptions() 
  52.      */  
  53.     @Override  
  54.     public Collection<String> supportedOptions() {  
  55.         return Collections.emptySet();  
  56.     }  
  57.   
  58. }  

 

使用下面命令:

apt -s . -nocompile -factory net.lazydoggy.annotations.aptdemo.InterfaceExtractorProcessorFactory .\net\lazydoggy\annotations\aptdemo\Multiplier.java

就会在当前执行目录下生成一个Imultiplier .java文件,里面定义了我们在处理器中写入的接口。

 

上面的程序运行时没有问题的,因为其中的一行代码被我改动过,如下:

Java代码  收藏代码
  1. for (MethodDeclaration m : typeDel.getMethods()) {  
  2.     if (m.getModifiers().toString().contains("public")  
  3.             && !(m.getModifiers().toString().contains("static"))) {  
  4.         interfaceMethods.add(m);  
  5.     }  
  6. }  

书中的代码是这样的:

Java代码  收藏代码
  1. for (MethodDeclaration m : typeDel.getMethods()) {  
  2.     if (m.getModifiers().contains(Modifier.PUBLIC)  
  3.             && !(m.getModifiers().contains(Modifier.STATIC))) {  
  4.         interfaceMethods.add(m);  
  5.     }  
  6. }  

 如果使用书中的代码是无法得到预期结果的,我使用JDK1.6,不知道JDK1.5是否可以。在JDK1.6中,getModifiers()返 回Collection<Modifier>类型,而Modifier类中的静态常量(PUBLIC、STATIC等)是int类型,因此书 中代码总会返回false。

上面是我的一个方法,应该有更好的方法,希望大家可以分享。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics