- 
                Notifications
    
You must be signed in to change notification settings  - Fork 38.8k
 
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