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



OBS:我的代码是java 8。例如,我有这样的stacktrace:

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

MethodA()→MethodB()→MethodC()→

MethodD ();

在我的例子中,ClassC:methodC()用@Cacheable.我需要在ClassFinal:MethodD()中获取注释,就像这样:

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

我已经使用反射完成了这一点,但它不适用于重载:

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;
}

我的程序的实际堆栈:

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)

test .a(test .java:14)被标注为@ cable
,我需要在sendGet(AbstractCommonIntegrationHttp.java:320)

中获得此注释我的注释:

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

我强烈建议使用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);
}
}

StackWalker.StackFrame包含区分不同重载所需的信息——即方法类型。
StackTraceElement只包含行号-如果您自己解析相应的类文件,这可能足够好-但这很快就会失控。

最新更新