Description
Ryan Stone opened SPR-1238 and commented
In the following code, in a MethodInterceptor, the target of the of the proxy is swapped with a HotSwappableTargetSource. However, when you call MethodInvocation.proceed(), the old target is still used for the current invocation. In subsequent invocations, the new target will be used.
//This interceptor:
public class TestCaseInterceptor implements MethodInterceptor, BeanFactoryAware {
private BeanFactory beanFactory;
private int count = 0;
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
count++;
if(count == 5) {
Advised bean = (Advised) AopContext.currentProxy();
HotSwappableTargetSource source = (HotSwappableTargetSource) bean.getTargetSource();
source.swap(beanFactory.getBean("target"));
System.out.println("swapping...");
count = 0;
}
return methodInvocation.proceed();
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
}
//the advised class:
public class ProxiedClass {
private static int nextInstanceId = 0;
private int instanceId;
public ProxiedClass() {
this.instanceId = nextInstanceId;
nextInstanceId++;
}
public void someMethod() {
System.out.println("This is instance #" + instanceId);
}
}
<!-- The Spring configuration file: -->
<beans>
<bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyTargetClass"><value>true</value></property>
<property name="singleton">
<value>false</value>
</property>
<property name="exposeProxy">
<value>true</value>
</property>
<property name="targetSource" ref="swapper"/>
<property name="interceptorNames">
<list>
<value>targetAdvisor</value>
</list>
</property>
</bean>
<bean id="targetAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor" singleton="false">
<constructor-arg>
<bean class="org.springframework.aop.TruePointcut"/>
</constructor-arg>
<constructor-arg>
<bean class="sdc.sade.common.spring_bug_testcase.TestCaseInterceptor"/>
</constructor-arg>
</bean>
<bean id="swapper" class="org.springframework.aop.target.HotSwappableTargetSource" singleton="false">
<constructor-arg>
<ref bean="target"/>
</constructor-arg>
</bean>
<bean id="target" class="sdc.sade.common.spring_bug_testcase.ProxiedClass" singleton="false"/>
</beans>
//The testcase:
public class TestCase {
public static void main(String [] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("testcase-context.xml");
ProxiedClass o = (ProxiedClass) context.getBean("proxy");
for(int i = 0; i < 20; i++) {
o.someMethod();
}
}
}
The output:
This is instance #0
This is instance #0
This is instance #0
This is instance #0
swapping...
This is instance #0
This is instance #2
This is instance #2
This is instance #2
This is instance #2
swapping...
This is instance #2
This is instance #3
This is instance #3
This is instance #3
This is instance #3
swapping...
This is instance #3
This is instance #4
This is instance #4
This is instance #4
This is instance #4
swapping...
This is instance #4
2 votes, 3 watchers