在应用它的方法中访问注释的值

时间:2014-07-20 08:53:22

标签: java reflection annotations

问题:有没有办法在应用它的方法中访问注释的值?

示例:假设我有一个这样的注释:

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    int value default 0;
}

接下来,我有一个带有函数f1 / f2的C类,它使用这个注释。该值在编译期间预先知道。

public class C {

    @MyAnnotation(value = 1)
    public void f1() {
         // Is there a way to get the 'value=1' here??
         g();
    }

    @MyAnnotation(value = -1)
    public void f2() {
         g();
    }
}

我有另一个函数g必须根据注释的值打印'正'或'负'或'零'。

public static void g() {
    // Must print 'positive' or 'negative' or 'zero'
}

1)f1 / f2是否有办法“捕获”注释的值并将其作为参数传递给g()?

2)我目前解决这个问题的方法是:

  • 在g()的类中进行初始化步骤,遍历所有C函数,并预先构造函数名称到值的散列图(例如:{'C.f1':1,'C。 f2': - 1})。为此,我使用getClass(),getMethods()和getAnnotations()并过滤只使用MyAnnotation。

  • 更改g()的签名以接受类和方法名称,并将其用作查看hashmap的键。 f1中的新调用将是g(this,“f1”)< - 我明确地写“f1”以避免在堆栈跟踪中查找方法名称。

毋庸置疑,这非常难看,我希望有一种更简单的方法可以做到这一点。谢谢。

编辑:我没有使用(并且不打算)用于此项目的Spring Framework。

1 个答案:

答案 0 :(得分:0)

我不确定在注释方法中访问注释信息是一个很好的设计选择。 Annotations表示不属于该计划的元信息。通常,程序运行程序可以通过反射创建对象和运行方法来访问它们。

如果要将属性或属性传递给方法,只需定义一个参数,该参数可由“runner”设置,具体取决于注释值。

但是,您可以使用Thread.currentThread().getStackTrace()方法找出使用的类和方法,然后访问注释信息。

以下是显示这两种方法的示例。它显示了如何在堆栈跟踪中找到当前方法以及如何通过反射运行程序并传递方法参数。

public class StackTrace {

    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public static  @interface MyAnnotation {
        int value() default 0;
    }

    public static class C {

        @MyAnnotation(value = 1)
        public void f1() { g(); }

        @MyAnnotation(value = -1)
        public void f2() {
            g();
        }
    }

    public static class X {
        @MyAnnotation(value = 1)
        public static void x1(int param) { System.out.println("Param1: " + param);}

        @MyAnnotation(value = -1)
        public static void x2(int param) { System.out.println("Param2: " + param); }
    }


    private static void g() {
        StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
        StackTraceElement traceElement = stackTraceElements[3];
        try {
            Class<?> type = Class.forName(traceElement.getClassName());
            String methodName = traceElement.getMethodName();
            Method method = type.getMethod(methodName);
            System.out.println(methodName + ": " +
                    method.getAnnotation(MyAnnotation.class).value());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void boo() throws InvocationTargetException, IllegalAccessException {
        for (Method m : X.class.getDeclaredMethods()) {
            MyAnnotation annotation = m.getAnnotation(MyAnnotation.class);
            if (annotation != null) {
                m.invoke(null, annotation.value());
            }
        }
    }

    public static void main(String[] args)
            throws InvocationTargetException, IllegalAccessException {
        C c = new C();
        c.f1();
        c.f2();

        boo();
    }
}

输出:

f1: 1
f2: -1
Param1: 1
Param2: -1