diff --git a/org.springframework.aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java b/org.springframework.aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java index 2c84dc19b3..dd568a51bd 100644 --- a/org.springframework.aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java +++ b/org.springframework.aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2010 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. @@ -97,6 +97,13 @@ public abstract class AopConfigUtils { } } + static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) { + if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { + BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); + definition.getPropertyValues().add("exposeProxy", Boolean.TRUE); + } + } + private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); diff --git a/org.springframework.aop/src/main/java/org/springframework/aop/config/AopNamespaceUtils.java b/org.springframework.aop/src/main/java/org/springframework/aop/config/AopNamespaceUtils.java index c00659027b..ae9888dca4 100644 --- a/org.springframework.aop/src/main/java/org/springframework/aop/config/AopNamespaceUtils.java +++ b/org.springframework.aop/src/main/java/org/springframework/aop/config/AopNamespaceUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2010 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. @@ -46,6 +46,11 @@ public abstract class AopNamespaceUtils { */ public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class"; + /** + * The expose-proxy attribute as found on AOP-related XML tags. + */ + private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy"; + public static void registerAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { @@ -102,6 +107,10 @@ public abstract class AopNamespaceUtils { if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } + boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); + if (exposeProxy) { + AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); + } } } diff --git a/org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java b/org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java index 9d649b62da..255d0b76ec 100644 --- a/org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java +++ b/org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-2010 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. @@ -268,7 +268,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { // Choose a "straight to target" interceptor. (used for calls that are // unadvised but can return this). May be required to expose the proxy. - Callback targetInterceptor = null; + Callback targetInterceptor; if (exposeProxy) { targetInterceptor = isStatic ? new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : @@ -316,12 +316,8 @@ final class Cglib2AopProxy implements AopProxy, Serializable { // Now copy both the callbacks from mainCallbacks // and fixedCallbacks into the callbacks array. callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; - for (int x = 0; x < mainCallbacks.length; x++) { - callbacks[x] = mainCallbacks[x]; - } - for (int x = 0; x < fixedCallbacks.length; x++) { - callbacks[x + mainCallbacks.length] = fixedCallbacks[x]; - } + System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length); + System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length); this.fixedInterceptorOffset = mainCallbacks.length; } else { @@ -610,7 +606,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable { targetClass = target.getClass(); } List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); - Object retVal = null; + Object retVal; // Check whether we only have one InvokerInterceptor: that is, // no real advice, but just reflective invocation of the target. if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { diff --git a/org.springframework.aop/src/main/java/org/springframework/aop/framework/ProxyConfig.java b/org.springframework.aop/src/main/java/org/springframework/aop/framework/ProxyConfig.java index a256e95c36..e012777285 100644 --- a/org.springframework.aop/src/main/java/org/springframework/aop/framework/ProxyConfig.java +++ b/org.springframework.aop/src/main/java/org/springframework/aop/framework/ProxyConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2010 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. @@ -113,12 +113,14 @@ public class ProxyConfig implements Serializable { * ThreadLocal for retrieval via the AopContext class. This is useful * if an advised object needs to call another advised method on itself. * (If it uses this, the invocation will not be advised). - *

Default is "false", for optimal performance. + *

Default is "false", in order to avoid unnecessary extra interception. + * This means that no guarantees are provided that AopContext access will + * work consistently within any method of the advised object. */ public void setExposeProxy(boolean exposeProxy) { this.exposeProxy = exposeProxy; } - + /** * Return whether the AOP proxy will expose the AOP proxy for * each invocation. diff --git a/org.springframework.aop/src/main/resources/org/springframework/aop/config/spring-aop-3.0.xsd b/org.springframework.aop/src/main/resources/org/springframework/aop/config/spring-aop-3.0.xsd index e7312e5ae4..879f57f7cc 100644 --- a/org.springframework.aop/src/main/resources/org/springframework/aop/config/spring-aop-3.0.xsd +++ b/org.springframework.aop/src/main/resources/org/springframework/aop/config/spring-aop-3.0.xsd @@ -56,6 +56,15 @@ ]]> + + + + + @@ -84,6 +93,15 @@ ]]> + + + + +