简体   繁体   English

使用反射或类似的东西在Java中获取子方法的注释

[英]Get children method's annotation in Java using reflection or something like this

OBS: My code is java 8. OBS:我的代码是 java 8。
For example, I have this stacktrace:例如,我有这个堆栈跟踪:

MainClass:MethodA() calls MainClass:MethodA() 调用
--------ClassB:MethodB() calls --------ClassB:MethodB() 调用
------------ClassC:MethodC() @Cacheable calls ------------ClassC:MethodC() @Cacheable调用
----------------ClassFinal:MethodD() ----------------ClassFinal:MethodD()

MethodA() -> MethodB() -> MethodC() -> MethodD();方法A() -> 方法B() -> 方法C() -> 方法D();


In my example, ClassC:methodC() it's noted with @Cacheable .在我的示例中, ClassC:methodC() 用@Cacheable 标注 I need get this annotation in ClassFinal:MethodD(), something like this:我需要在 ClassFinal:MethodD() 中获取此注释,如下所示:

    public void MethodD() {
        Cacheable cacheable = ...
    }

I already done this using reflection, but it isn't work with overload:我已经使用反射完成了这项工作,但它不适用于重载:

    public static <T extends Annotation> T getStacktraceAnnotation(Class<T> type) {
        int currStack = 0;
        T result = null;
        
        //
        //
        StackTraceElement[] stackTraceElementArray = Thread.currentThread().getStackTrace();
        
        //
        //
        for (java.lang.StackTraceElement curr : stackTraceElementArray) {
            try {
                Method[] methods = Class.forName(curr.getClassName()).getMethods();
                
                for (Method currMethod : methods) 
                    if (currMethod.getName().equals(curr.getMethodName())) {
                        result = currMethod.getAnnotation(type);
                        if (result != null) break;
                    }
                //
                //
                if (result != null || currStack++ > 6) break;
            } catch(Exception exc) {
                // Nothing!
            }
        }
        //
        //
        return result;
    }

Real stacktace of my program:我的程序的真正堆栈:

fff.commons.serverless.abstracts.v2.AbstractCommonIntegrationHttp.sendGet(AbstractCommonIntegrationHttp.java:320) 
fff.commons.serverless.abstracts.v2.Teste.a(Teste.java:14) 
fff.commons.serverless.abstracts.v2.Teste.main(Teste.java:18)

Teste.a(Teste.java:14) is noted with @Cachable Teste.a(Teste.java:14) 用@Cachable 标注
And I need get this anottation in sendGet(AbstractCommonIntegrationHttp.java:320)我需要在 sendGet(AbstractCommonIntegrationHttp.java:320) 中得到这个注释

My annotation:我的注释:

@Retention(RUNTIME)
@Target({ TYPE, METHOD })
@Inherited
public @interface Cacheable {
    int secs() default 15;
}

I strongly suggest using a StackWalker instead:我强烈建议改用StackWalker

private static final StackWalker SW = StackWalker
        .getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);

public static <T extends Annotation> T getStacktraceAnnotation(Class<T> type) {
    return SW.walk(s -> s.map(sf -> getMethodAnnotation(type, sf)).filter(Objects::nonNull)
            .findFirst()).orElseThrow();
}

private static <T extends Annotation> T getMethodAnnotation(Class<T> annotationClass,
        StackFrame sf) {
    try {
        return sf.getDeclaringClass()
                .getDeclaredMethod(sf.getMethodName(), sf.getMethodType().parameterArray())
                .getAnnotation(annotationClass);
    } catch (NoSuchMethodException e) {
        throw new RuntimeException(e);
    }
}

The StackWalker.StackFrame contains the information needed to distinguish between different overloads - namely the method type. StackWalker.StackFrame包含区分不同重载所需的信息——即方法类型。
A StackTraceElement only contains the line number - which might be good enough if you parse the corresponding class file yourself - but this gets quickly out of hand. StackTraceElement仅包含行号 - 如果您自己解析相应的类文件,这可能就足够了 - 但这很快就会失控。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM