Description
Yoni Amir opened SPR-13990 and commented
I have a spring context setup like this:
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
<bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
I have a custom advisor, not shown in the XML snippet above, that searches for some annotations at the class level of the beans that Spring creates.
The problem is that the PersistenceExceptionTranslationPostProcessor
runs first and creates a proxy around the bean. When the DefaultAdvisorAutoProxyCreator
runs, it calls getClass()
on the proxied bean and passes that class (something like com.sun.proxy.$Proxy) to the advisor to test for a match. The advisor is then unable to detect the annotations.
The flawed call to getClass()
is in AbstractAutoProxyCreater.wrapIfNecessary()
method, just before calling getAdvicesAndAdvisorsForBean()
.
There is a workaround, though. Adding an order attribute and ensuring that the DefaultAdvisorAutoProxyCreator
runs first works. This is because the PersistenceExceptionTranslationPostProcessor
can handle beans that are already proxied - it extract the target class of the proxy. This happens in AbstractAdvisingBeanPostProcessor.postProcessAfterInitialization()
method. The relevant code looks more or less like this:
if (bean instanceof Advised) {
Advised advised = (Advised) bean;
if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
This workaround has a limitation, though. It forces a certain order in which the interceptors run, which may not be the order that I want.
Bottom line is, I think AbstractAutoProxyCreater.wrapIfNecessary()
(which is called from AbstractAutoProxyCreater.postProcessAfterInitialization()
needs to use the code snippet above and act similarly to AbstractAdvisingBeanPostProcessor.postProcessAfterInitialization()
Issue Links:
- AnnotationAwareOrderComparator getPriority does not work if bean is a proxy [SPR-13884] #18457 AnnotationAwareOrderComparator getPriority does not work if bean is a proxy