From 43c1cec79b908b084de8de65d98c42a401443250 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 13 Mar 2013 14:36:09 +0100 Subject: [PATCH] Added "beforeExistingAdvisors" flag to AbstractAdvisingBeanPostProcessor Just AsyncAnnotationBeanPostProcessor switches "beforeExistingAdvisors" to "true" by default. So effectively, MethodValidation/PersistenceExceptionTranslationPostProcessor apply after existing advisors by default again, fixing the 3.1->3.2 regression. Issue: SPR-10309 --- .../AbstractAdvisingBeanPostProcessor.java | 23 ++++++++++++++++++- .../AsyncAnnotationBeanPostProcessor.java | 10 +++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java b/spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java index 5d76f6c8a5e8..01b0fe856c37 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/AbstractAdvisingBeanPostProcessor.java @@ -39,6 +39,8 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig protected Advisor advisor; + protected boolean beforeExistingAdvisors = false; + private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); /** @@ -50,6 +52,19 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig private final Map eligibleBeans = new ConcurrentHashMap(64); + /** + * Set whether this post-processor's advisor is supposed to apply before + * existing advisors when encountering a pre-advised object. + *

Default is "false", applying the advisor after existing advisors, i.e. + * as close as possible to the target method. Switch this to "true" in order + * for this post-processor's advisor to wrap existing advisors as well. + *

Note: Check the concrete post-processor's javadoc whether it possibly + * changes this flag by default, depending on the nature of its advisor. + */ + public void setBeforeExistingAdvisors(boolean beforeExistingAdvisors) { + this.beforeExistingAdvisors = beforeExistingAdvisors; + } + public void setBeanClassLoader(ClassLoader beanClassLoader) { this.beanClassLoader = beanClassLoader; } @@ -74,7 +89,13 @@ public Object postProcessAfterInitialization(Object bean, String beanName) { } if (isEligible(bean, beanName)) { if (bean instanceof Advised) { - ((Advised) bean).addAdvisor(0, this.advisor); + Advised advised = (Advised) bean; + if (this.beforeExistingAdvisors) { + advised.addAdvisor(0, this.advisor); + } + else { + advised.addAdvisor(this.advisor); + } return bean; } else { diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java index f4c7d65125e2..0ac2f757f033 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/AsyncAnnotationBeanPostProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,11 +38,15 @@ * processor will detect both Spring's {@link Async @Async} annotation as well * as the EJB 3.1 {@code javax.ejb.Asynchronous} annotation. * + *

Note: The underlying async advisor applies before existing advisors by default, + * in order to switch to async execution as early as possible in the invocation chain. + * * @author Mark Fisher * @author Juergen Hoeller * @since 3.0 * @see Async * @see AsyncAnnotationAdvisor + * @see #setBeforeExistingAdvisors */ @SuppressWarnings("serial") public class AsyncAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostProcessor @@ -53,6 +57,10 @@ public class AsyncAnnotationBeanPostProcessor extends AbstractAdvisingBeanPostPr private Executor executor; + public AsyncAnnotationBeanPostProcessor() { + setBeforeExistingAdvisors(true); + } + /** * Set the 'async' annotation type to be detected at either class or method * level. By default, both the {@link Async} annotation and the EJB 3.1