All I wanted to find out was "all the class/methods in Spring beans which are annotated as @Versioned".
I created my custom annotation as,
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Versioned {
.....
}
This annotation works perfectly when I use Java reflection to find methods as:
for(Method m: obj.getClass().getMethods()){
if(m.isAnnotationPresent(Versioned.class)){
.... // Do something
}
But it does not work when I access Spring beans and try similar check:
public class VersionScanner implements ApplicationContextAware{
public void setApplicationContext(ApplicationContext applicationContext){
for(String beanName: applicationContext.getBeanDefinitionNames()){
for(Method m: applicationContext.getBean(beanName).getClass().getDeclaredMethods()){
if(m.isAnnotationPresent(Versioned.class){
// This is not WORKING as expected for any beans with method annotated
}
}
}
}
}
In fact, this code does find other annotations such as @RequestMapping. I am not sure what I am doing wrong with my custom annotation.
@Bean. This annotation is used at the method level.
The isAnnotation() method is used to check whether a class object is an annotation. The isAnnotation() method has no parameters and returns a boolean value. If the return value is true , then the class object is an annotation. If the return value is false , then the class object is not an annotation.
@Bean is a method-level annotation and a direct analog of the XML <bean/> element. The annotation supports most of the attributes offered by <bean/> , such as: init-method , destroy-method , autowiring , lazy-init , dependency-check , depends-on and scope .
Annotation is defined like a ordinary Java interface, but with an '@' preceding the interface keyword (i.e., @interface ). You can declare methods inside an annotation definition (just like declaring abstract method inside an interface). These methods are called elements instead.
Going through your code, I figured out that you are using Spring AOP with CGLIB Proxying. Due to which your classes (which have methods annotated with @Versioned
) are being proxied.
I have tested this solution with your code base.
Use the following code, and it should resolve your issue. Look for more options below the code snippet:
@Configuration
public class VersionScanner implements ApplicationContextAware {
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
for (String beanName : applicationContext.getBeanDefinitionNames()) {
Object obj = applicationContext.getBean(beanName);
/*
* As you are using AOP check for AOP proxying. If you are proxying with Spring CGLIB (not via Spring AOP)
* Use org.springframework.cglib.proxy.Proxy#isProxyClass to detect proxy If you are proxying using JDK
* Proxy use java.lang.reflect.Proxy#isProxyClass
*/
Class<?> objClz = obj.getClass();
if (org.springframework.aop.support.AopUtils.isAopProxy(obj)) {
objClz = org.springframework.aop.support.AopUtils.getTargetClass(obj);
}
for (Method m : objClz.getDeclaredMethods()) {
if (m.isAnnotationPresent(Versioned.class)) {
//Should give you expected results
}
}
}
}
}
To detect a proxy class:
org.springframework.aop.support.AopUtils#isAoPProxy
org.springframework.cglib.proxy.Proxy#isProxyClass
java.lang.reflect.Proxy#isProxyClass
I have just written one if
condition which is sufficient in your case; but in case multiple proxying utilities are used, multiple if-else
conditions will have to be written based on the information above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With