I have created my own annotation for classes: @MyAnnotation
, and have annotated two classes with it.
I have also annotated a few methods in these classes with Spring's @Transactional
. According to the Spring documentation for Transaction Management, the bean factory actually wraps my class into a proxy.
Last, I use the following code to retrieve the annotated beans.
getBeansWithAnnotation
correctly returns my declared beans. Good.
@Transactional
attribute is found and works.MyAnnotation
in the bean. Bad. I wish I could read this annotation from the actual classes or proxies seamlessly.If a bean is a proxy, how can I find the annotations on the actual class ?
What should I be using instead of AnnotationUtils.findAnnotation()
for the desired result ?
Map<String,Object> beans = ctx.getBeansWithAnnotation(MyAnnotation.class);
System.out.println(beans.size());
// prints 2. ok !
for (Object bean: services.values()) {
System.out.println(bean.getClass());
// $Proxy
MyAnnotation annotation = AnnotationUtils.findAnnotation(svc.getClass(), MyAnnotation.class);
//
// Problem ! annotation is null !
//
}
Access the BeanFactory. Look up the BeanDefinition associated with each bean. Check if the source of the BeanDefinition is an AnnotatedTypeMetadata, which means we'll be able to access the annotations of the bean.
@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 .
Spring @Bean Annotation is applied on a method to specify that it returns a bean to be managed by Spring context. Spring Bean annotation is usually declared in Configuration classes methods. In this case, bean methods may reference other @Bean methods in the same class by calling them directly.
@Bean is just for the metadata definition to create the bean(equivalent to tag). @Autowired is to inject the dependancy into a bean(equivalent to ref XML tag/attribute).
You can find the real class of the proxied bean by calling AopProxyUtils.ultimateTargetClass.
Determine the ultimate target class of the given bean instance, traversing not only a top-level proxy but any number of nested proxies as well - as long as possible without side effects, that is, just for singleton targets.
The solution is not to work on the bean itself, but to ask the application context instead.
Use method ApplicationContext#findAnnotationOnBean(String,Class).
Map<String,Object> beans = ctx.getBeansWithAnnotation(MyAnnotation.class);
System.out.println(beans.size());
// prints 2. ok !
for (Object bean: services.values()) {
System.out.println(bean.getClass());
// $Proxy
/* MyAnnotation annotation = AnnotationUtils.findAnnotation(svc.getClass(), MyAnnotation.class);
// Problem ! annotation is null !
*/
MyAnnotation annotation = ctx.findAnnotationOnBean(beanName, MyAnnotation.class);
// Yay ! Correct !
}
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