Java 自定义批注处理器-使用批注检测方法

Java 自定义批注处理器-使用批注检测方法,java,annotations,annotation-processing,Java,Annotations,Annotation Processing,我正试图编写一个注释处理器来检测用@PrintMethod注释的方法。例如,在下面的测试类中,我想打印测试方法中的代码。有办法吗 从下面所述的AnnotationProcessor类中,我只能获得方法名称,但无法获得方法的详细信息 测试类 public class test { public static void main(String[] args) { System.out.println("Args"); } @PrintMethod

我正试图编写一个注释处理器来检测用@PrintMethod注释的方法。例如,在下面的测试类中,我想打印测试方法中的代码。有办法吗

从下面所述的AnnotationProcessor类中,我只能获得方法名称,但无法获得方法的详细信息

测试类

public class test {

    public static void main(String[] args) {
        System.out.println("Args");
    }

    @PrintMethod
    private boolean testMethod(String input) {
        if(input!=null) {  
            return true;
        }
        return false; 
    }
}
public class AnnotationProcessor extends AbstractProcessor {
//......
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        //retrieve test Anntoation
        Set<? extends Element> ann =roundEnv.getElementsAnnotatedWith(PrintMethod.class);

        //Print the Method Name
        for(Element e: ann) {
            String msg="Element ee :"+ee.getSimpleName().toString();
            processingEnv.getMessager().printMessage( javax.tools.Diagnostic.Kind.ERROR, msg, e);
        }
    }
}
注释处理器类

public class test {

    public static void main(String[] args) {
        System.out.println("Args");
    }

    @PrintMethod
    private boolean testMethod(String input) {
        if(input!=null) {  
            return true;
        }
        return false; 
    }
}
public class AnnotationProcessor extends AbstractProcessor {
//......
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        //retrieve test Anntoation
        Set<? extends Element> ann =roundEnv.getElementsAnnotatedWith(PrintMethod.class);

        //Print the Method Name
        for(Element e: ann) {
            String msg="Element ee :"+ee.getSimpleName().toString();
            processingEnv.getMessager().printMessage( javax.tools.Diagnostic.Kind.ERROR, msg, e);
        }
    }
}
公共类AnnotationProcessor扩展了AbstractProcessor{
//......
@凌驾

public boolean process(Set我对此也很好奇,所以我决定尝试解决它。结果比我预期的要简单。您需要做的就是利用专有tools.jar库中的
api。我在这里制作了一个快速注释处理器:

下面是它的要点:

@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("org.printMethod.PrintMethod")
public class PrintMethodAnnotationProcessor extends AbstractProcessor {

    private Trees trees;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        trees = Trees.instance(processingEnv); //initialize the Trees api.
    }

    @Override
    public boolean process(Set<? extends TypeElement> typeElements, RoundEnvironment roundEnvironment) {

        MethodPrintScanner visitor = new MethodPrintScanner();

        for (Element e : roundEnvironment.getElementsAnnotatedWith(PrintMethod.class)) {
            TreePath tp = trees.getPath(e);
            // visit the annotated methods
            visitor.scan(tp, trees);
        }
        return true;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }
}
您可以看到,我们可以访问与给定的带注释元素关联的
TreePath
。对于每个方法,我们只需
println()
方法树,它提供了方法的内容

使用您的示例,以下是编译期间程序的输出:

@PrintMethod()
private boolean testMethod(String input) {
    if (input != null) {
        return true;
    }
    return false;
}

我对此也很好奇,所以我决定尝试解决它。结果比我预期的要简单。你所需要做的就是利用专有tools.jar库中的
api。我已经按照以下思路制作了一个快速注释处理器:

下面是它的要点:

@SupportedSourceVersion(SourceVersion.RELEASE_6)
@SupportedAnnotationTypes("org.printMethod.PrintMethod")
public class PrintMethodAnnotationProcessor extends AbstractProcessor {

    private Trees trees;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        trees = Trees.instance(processingEnv); //initialize the Trees api.
    }

    @Override
    public boolean process(Set<? extends TypeElement> typeElements, RoundEnvironment roundEnvironment) {

        MethodPrintScanner visitor = new MethodPrintScanner();

        for (Element e : roundEnvironment.getElementsAnnotatedWith(PrintMethod.class)) {
            TreePath tp = trees.getPath(e);
            // visit the annotated methods
            visitor.scan(tp, trees);
        }
        return true;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }
}
您可以看到,我们可以访问与给定的带注释元素关联的
TreePath
。对于每个方法,我们只需
println()
方法树,它提供了方法的内容

使用您的示例,以下是编译期间程序的输出:

@PrintMethod()
private boolean testMethod(String input) {
    if (input != null) {
        return true;
    }
    return false;
}

让它在IDE中工作是一回事,但在jar文件中打包代码后检测它们又是另一回事

public static List<Class> getPackageClassListHavingAnnotation(String pPackageName,
                                                              Class<? extends Annotation> pAnnotation) throws Exception
{
  try
  {
    List<Class> classList = getPackageClassList(pPackageName);
    if ((pAnnotation == null) || (classList == null)) return classList;

    List<Class> resultList = new ArrayList<Class>(classList.size());

    outerLoop:
    for (Class clazz : classList)
    {
      try
      {
        for (Method method : clazz.getMethods())
        {
          if (method.isAnnotationPresent(pAnnotation))
          {
            resultList.add(clazz);
            continue outerLoop;
          }
        }
      }
      catch (Throwable e)
      {
      }
    }
    return (resultList.isEmpty()) ? null : resultList;
  }
  catch (Exception e)
  {
    return null;
  }
}
公共静态列表getPackageClassListHavingAnnotation(字符串pPackageName,

类使其在IDE中工作是一回事,但在jar文件中打包代码后检测它们又是另一回事。下面的代码可以同时管理这两者

public static List<Class> getPackageClassListHavingAnnotation(String pPackageName,
                                                              Class<? extends Annotation> pAnnotation) throws Exception
{
  try
  {
    List<Class> classList = getPackageClassList(pPackageName);
    if ((pAnnotation == null) || (classList == null)) return classList;

    List<Class> resultList = new ArrayList<Class>(classList.size());

    outerLoop:
    for (Class clazz : classList)
    {
      try
      {
        for (Method method : clazz.getMethods())
        {
          if (method.isAnnotationPresent(pAnnotation))
          {
            resultList.add(clazz);
            continue outerLoop;
          }
        }
      }
      catch (Throwable e)
      {
      }
    }
    return (resultList.isEmpty()) ? null : resultList;
  }
  catch (Exception e)
  {
    return null;
  }
}
公共静态列表getPackageClassListHavingAnnotation(字符串pPackageName,
等级