'Get children method's annotation in Java using reflection or something like this
OBS: My code is java 8.
For example, I have this stacktrace:
MainClass:MethodA() calls
--------ClassB:MethodB() calls
------------ClassC:MethodC() @Cacheable calls
----------------ClassFinal:MethodD()
MethodA() -> MethodB() -> MethodC() -> MethodD();
In my example, ClassC:methodC() it's noted with @Cacheable. I need get this annotation in ClassFinal:MethodD(), something like this:
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
And I need get this anottation in sendGet(AbstractCommonIntegrationHttp.java:320)
My annotation:
@Retention(RUNTIME)
@Target({ TYPE, METHOD })
@Inherited
public @interface Cacheable {
int secs() default 15;
}
Solution 1:[1]
I strongly suggest using a StackWalker instead:
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.
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Johannes Kuhn |
