如何使用给定的注释运行所有方法?

时间:2013-06-08 04:26:57

标签: java reflection annotations

这就是我想要发生的事情:

public class MainClass {
    public static void main(String args[]) { 
        run @mod(); // run all methods annotated with @mod annotation
    }
}

注释声明:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface mod {
   String name() default "";
}

要调用的方法

public class Good {
    @mod (name = "me1")
    public void calledcs(){
        System.out.println("called");
    }

    @mod (name = "me2")
    public void calledcs2(){
        System.out.println("called");
    }
}

还是有另一种方法来实现同样的目标吗?

3 个答案:

答案 0 :(得分:4)

您可以使用类路径扫描来执行此操作:基本上,您将遍历类路径中每个类的每个方法,并使用给定的注释进行所有注释。之后,您调用找到的方法。

下面是一个runAllAnnotatedWith()方法。它使用 Reflections 来完成类路径扫描的脏工作。 为简单起见,它会执行所有找到的方法,就像它们是static并且不需要参数一样。

public static void runAllAnnotatedWith(Class<? extends Annotation> annotation)
                                                               throws Exception {
    Reflections reflections = new Reflections(new ConfigurationBuilder()
                                  .setUrls(ClasspathHelper.forJavaClassPath())
                                  .setScanners(new MethodAnnotationsScanner()));
    Set<Method> methods = reflections.getMethodsAnnotatedWith(annotation);

    for (Method m : methods) {
        // for simplicity, invokes methods as static without parameters
        m.invoke(null); 
    }
}

您可以使用以下方式运行它:

runAllAnnotatedWith(mod.class);

注意:可以在不使用Reflections的情况下执行此操作,但代码会变得更脏,更脏。

以下是完整代码(将其全部粘贴到RunClass.java文件中):

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.Set;

import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;

public class RunClass {
    public static void main(String args[]) throws Exception {
        runAllAnnotatedWith(mod.class);
    }

    public static void runAllAnnotatedWith(Class<? extends Annotation> annotation) throws Exception {
        Reflections reflections = new Reflections(new ConfigurationBuilder()
                .setUrls(ClasspathHelper.forJavaClassPath()).setScanners(
                        new MethodAnnotationsScanner()));
        Set<Method> methods = reflections.getMethodsAnnotatedWith(annotation);

        for (Method m : methods) {
            m.invoke(null); // for simplicity, invoking static methods without parameters
        }
    }

    @mod(name = "me1")
    public static void calledcs() {
        System.out.println("called");
    }

    @mod(name = "me2")
    public static void calledcs2() {
        System.out.println("called2");
    }
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface mod {
    String name() default "";
}

要运行它,您必须将Reflections JAR添加到项目中。的 Download it here

如果您使用Maven,可以使用以下方式添加:

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.9-RC1</version>
</dependency>

答案 1 :(得分:3)

这是一个使用我最近发布的开源库的例子,名为Reflect:

List<Method> methods = Reflect.on(someClass).methods().annotatedWith(mod.class);
for (Method m : methods) {
  m.invoke(null);
}

Maven依赖:

<dependency>
    <groupId>org.pacesys</groupId>
    <artifactId>reflect</artifactId>
    <version>1.0.0</version>
</dependency>

更多食谱见于:https://github.com/gondor/reflect

答案 2 :(得分:1)

我认为你可以使用反射技术。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface mod {
   public String name() default "";
}

public class Fundamental {
   public static void main(String[] args) {
      // Get all methods in order.
      // runClass is the class you declare all methods with annotations.
      Method[] methods = runClass.getMethods();
      for(Method mt : methods) {
        if (mt.isAnnotationPresent(mod.class)) {
            // Invoke method with appropriate arguments
            Object obj = mt.invoke(runClass, null);
        }
      } 
   }
}