Skip to content

Commit fe1e7f0

Browse files
committed
added "expose-proxy" attribute to aop namespace (enforcing AopContext proxy exposure with CGLIB; SPR-7261)
1 parent 857faec commit fe1e7f0

File tree

5 files changed

+46
-14
lines changed

5 files changed

+46
-14
lines changed

org.springframework.aop/src/main/java/org/springframework/aop/config/AopConfigUtils.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2010 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -97,6 +97,13 @@ public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistr
9797
}
9898
}
9999

100+
static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
101+
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
102+
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
103+
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
104+
}
105+
}
106+
100107

101108
private static BeanDefinition registerOrEscalateApcAsRequired(Class cls, BeanDefinitionRegistry registry, Object source) {
102109
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

org.springframework.aop/src/main/java/org/springframework/aop/config/AopNamespaceUtils.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2010 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -46,6 +46,11 @@ public abstract class AopNamespaceUtils {
4646
*/
4747
public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";
4848

49+
/**
50+
* The <code>expose-proxy</code> attribute as found on AOP-related XML tags.
51+
*/
52+
private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";
53+
4954

5055
public static void registerAutoProxyCreatorIfNecessary(
5156
ParserContext parserContext, Element sourceElement) {
@@ -102,6 +107,10 @@ private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry,
102107
if (proxyTargetClass) {
103108
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
104109
}
110+
boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
111+
if (exposeProxy) {
112+
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
113+
}
105114
}
106115
}
107116

org.springframework.aop/src/main/java/org/springframework/aop/framework/Cglib2AopProxy.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2010 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -268,7 +268,7 @@ private Callback[] getCallbacks(Class rootClass) throws Exception {
268268

269269
// Choose a "straight to target" interceptor. (used for calls that are
270270
// unadvised but can return this). May be required to expose the proxy.
271-
Callback targetInterceptor = null;
271+
Callback targetInterceptor;
272272
if (exposeProxy) {
273273
targetInterceptor = isStatic ?
274274
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
@@ -316,12 +316,8 @@ private Callback[] getCallbacks(Class rootClass) throws Exception {
316316
// Now copy both the callbacks from mainCallbacks
317317
// and fixedCallbacks into the callbacks array.
318318
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
319-
for (int x = 0; x < mainCallbacks.length; x++) {
320-
callbacks[x] = mainCallbacks[x];
321-
}
322-
for (int x = 0; x < fixedCallbacks.length; x++) {
323-
callbacks[x + mainCallbacks.length] = fixedCallbacks[x];
324-
}
319+
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
320+
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
325321
this.fixedInterceptorOffset = mainCallbacks.length;
326322
}
327323
else {
@@ -610,7 +606,7 @@ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy
610606
targetClass = target.getClass();
611607
}
612608
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
613-
Object retVal = null;
609+
Object retVal;
614610
// Check whether we only have one InvokerInterceptor: that is,
615611
// no real advice, but just reflective invocation of the target.
616612
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {

org.springframework.aop/src/main/java/org/springframework/aop/framework/ProxyConfig.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2007 the original author or authors.
2+
* Copyright 2002-2010 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -113,12 +113,14 @@ public boolean isOpaque() {
113113
* ThreadLocal for retrieval via the AopContext class. This is useful
114114
* if an advised object needs to call another advised method on itself.
115115
* (If it uses <code>this</code>, the invocation will not be advised).
116-
* <p>Default is "false", for optimal performance.
116+
* <p>Default is "false", in order to avoid unnecessary extra interception.
117+
* This means that no guarantees are provided that AopContext access will
118+
* work consistently within any method of the advised object.
117119
*/
118120
public void setExposeProxy(boolean exposeProxy) {
119121
this.exposeProxy = exposeProxy;
120122
}
121-
123+
122124
/**
123125
* Return whether the AOP proxy will expose the AOP proxy for
124126
* each invocation.

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,15 @@
5656
]]></xsd:documentation>
5757
</xsd:annotation>
5858
</xsd:attribute>
59+
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
60+
<xsd:annotation>
61+
<xsd:documentation><![CDATA[
62+
Indicate that the proxy should be exposed by the AOP framework as a
63+
ThreadLocal for retrieval via the AopContext class. Off by default,
64+
i.e. no guarantees that AopContext access will work.
65+
]]></xsd:documentation>
66+
</xsd:annotation>
67+
</xsd:attribute>
5968
</xsd:complexType>
6069
</xsd:element>
6170

@@ -84,6 +93,15 @@
8493
]]></xsd:documentation>
8594
</xsd:annotation>
8695
</xsd:attribute>
96+
<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
97+
<xsd:annotation>
98+
<xsd:documentation><![CDATA[
99+
Indicate that the proxy should be exposed by the AOP framework as a
100+
ThreadLocal for retrieval via the AopContext class. Off by default,
101+
i.e. no guarantees that AopContext access will work.
102+
]]></xsd:documentation>
103+
</xsd:annotation>
104+
</xsd:attribute>
87105
</xsd:complexType>
88106
</xsd:element>
89107

0 commit comments

Comments
 (0)