Browse Source

added "expose-proxy" attribute to aop namespace (enforcing AopContext proxy exposure with CGLIB; SPR-7261)

pull/1234/head
Juergen Hoeller 15 years ago
parent
commit
fe1e7f0d6c
  1. 9
      org.springframework.aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java
  2. 11
      org.springframework.aop/src/main/java/org/springframework/aop/config/AopNamespaceUtils.java
  3. 14
      org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java
  4. 8
      org.springframework.aop/src/main/java/org/springframework/aop/framework/ProxyConfig.java
  5. 18
      org.springframework.aop/src/main/resources/org/springframework/aop/config/spring-aop-3.0.xsd

9
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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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) { private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

11
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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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"; public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";
/**
* The <code>expose-proxy</code> attribute as found on AOP-related XML tags.
*/
private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";
public static void registerAutoProxyCreatorIfNecessary( public static void registerAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) { ParserContext parserContext, Element sourceElement) {
@ -102,6 +107,10 @@ public abstract class AopNamespaceUtils {
if (proxyTargetClass) { if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
} }
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
} }
} }

14
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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 // Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy. // unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor = null; Callback targetInterceptor;
if (exposeProxy) { if (exposeProxy) {
targetInterceptor = isStatic ? targetInterceptor = isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
@ -316,12 +316,8 @@ final class Cglib2AopProxy implements AopProxy, Serializable {
// Now copy both the callbacks from mainCallbacks // Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array. // and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
for (int x = 0; x < mainCallbacks.length; x++) { System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
callbacks[x] = mainCallbacks[x]; System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
}
for (int x = 0; x < fixedCallbacks.length; x++) {
callbacks[x + mainCallbacks.length] = fixedCallbacks[x];
}
this.fixedInterceptorOffset = mainCallbacks.length; this.fixedInterceptorOffset = mainCallbacks.length;
} }
else { else {
@ -610,7 +606,7 @@ final class Cglib2AopProxy implements AopProxy, Serializable {
targetClass = target.getClass(); targetClass = target.getClass();
} }
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal = null; Object retVal;
// Check whether we only have one InvokerInterceptor: that is, // Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target. // no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {

8
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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with 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 * ThreadLocal for retrieval via the AopContext class. This is useful
* if an advised object needs to call another advised method on itself. * if an advised object needs to call another advised method on itself.
* (If it uses <code>this</code>, the invocation will not be advised). * (If it uses <code>this</code>, the invocation will not be advised).
* <p>Default is "false", for optimal performance. * <p>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) { public void setExposeProxy(boolean exposeProxy) {
this.exposeProxy = exposeProxy; this.exposeProxy = exposeProxy;
} }
/** /**
* Return whether the AOP proxy will expose the AOP proxy for * Return whether the AOP proxy will expose the AOP proxy for
* each invocation. * each invocation.

18
org.springframework.aop/src/main/resources/org/springframework/aop/config/spring-aop-3.0.xsd

@ -56,6 +56,15 @@
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicate that the proxy should be exposed by the AOP framework as a
ThreadLocal for retrieval via the AopContext class. Off by default,
i.e. no guarantees that AopContext access will work.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
@ -84,6 +93,15 @@
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicate that the proxy should be exposed by the AOP framework as a
ThreadLocal for retrieval via the AopContext class. Off by default,
i.e. no guarantees that AopContext access will work.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>

Loading…
Cancel
Save