[英]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.