BeanNameAutoProxyCreator proxies the wrong beans when custom TargetSourceCreator specified
See original GitHub issueSpring 5.1.8 (but also probably earlier versions)
Short version: if you use BeanNameAutoProxyCreator
with a custom TargetSourceCreator
, you’ll get proxies created for all of your beans, not just the ones listed in the beanNames
property.
Longer version: BeanNameAutoProxyCreator
allows you to specify the beanNames
for which you want proxies to be created. It also allows you to specify one of more TargetSourceCreators
. However, the TargetSourceCreator
will be asked to create TargetSource
for every bean in the context, not just the beans listed in beanNames
.
To reproduce the problem, I created a simple context with 2 beans and a unit test (see below). The context contains a BeanNameAutoProxyCreator
and specifies that only beanA
should be proxied. Both beanA
and beanB
are declared as lazy-init
, and I’ve specified a LazyInitTargetSourceCreator
to be used (the lazy-init-ness isn’t particularly important, it’s just an off-the-shelf implementation of TargetSourceCreator
that demonstrates the problem).
The unit test asserts that BeanA
is a proxy and beanB
is not, but then fails because both beans have been proxied.
This is at the very least unexpected and confusing (and should be documented), and is probably a bug. The TargetSourceCreator
is being asked for a TargetSource
for every bean in the context, without checking for which beans should be candidates for being proxied.
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="beanA" class="test.BeanNameAutoProxyBugTest.ClassA" lazy-init="true"/>
<bean id="beanB" class="test.BeanNameAutoProxyBugTest.ClassB" lazy-init="true"/>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames" value="beanA"/>
<property name="customTargetSourceCreators">
<bean class="org.springframework.aop.framework.autoproxy.target.LazyInitTargetSourceCreator"/>
</property>
</bean>
</beans>
package test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.aop.SpringProxy;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import javax.inject.Inject;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/context.xml")
@TestExecutionListeners(DependencyInjectionTestExecutionListener.class)
public class BeanNameAutoProxyBugTest {
@Inject
ClassA beanA;
@Inject
ClassB beanB;
@Test
public void test() {
assertThat("beanA should be proxied", beanA, instanceOf(SpringProxy.class));
assertThat("beanB should not be proxied", beanB, not(instanceOf(SpringProxy.class)));
}
static class ClassA {
}
static class ClassB {
}
}
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (4 by maintainers)
Top GitHub Comments
That was my hope, but I appreciate that this is old code, old enough as you say that people my be relying on the “broken” behaviour, which makes it hard to back-port.
Thanks for the feedback, @kennymacleod.
This has been addressed in 3c3e8e6a8bfd45e8f1c3f1df5c7ef66d85d5d5f1 for Spring Framework 5.3.