Friday, February 4, 2011

Spring AOP - Changing target of a Proxy at runtime

I had a pretty strange usecase where i wanted to change the target object of the proxy and runtime. Spring makes it so simple to use.

My usecase was as follows

ApplicationContext ctx = new ClassPathXmlApplicationContext(
AccountDAO accountDao = (AccountDAO) ctx.getBean("accountDao");

IAccount account = accountDao.getById(123);

System.out.println("account" + account);


System.out.println("account" + account);

Is a property is change on the entity , i want to change the entity object itself , that is , in the above use two sysouts will print different objects.

The use case arose because i was using a cache(infinispan) which did not allow modifying POJOs outside a transaction scope.

I did achieve the same using the follwing

public class AccountDAO {

private Advisor advisor;

//This is get methods of the accountDao

public IAccount getById(long id) {
//creating new account - to mock database behavior
IAccount a = new Account(369, "suji");
//Using spring factory
ProxyFactory pf = new ProxyFactory();
//Using by own Target source to change the Target
pf.setTargetSource(new SwappableTargetSource(a));
//advisor which holds the advice and pointcut
return (IAccount) pf.getProxy();

public void setAdvisor(Advisor advisor) {
this.advisor = advisor;


My advice class

public class SwappableBeforeAdvice implements MethodBeforeAdvice {

public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("Before advice called");

if (!((IAccount) target).isWritable()) {

//Changing the target source based on specific business condition
((SwappableTargetSource) ((Advised) AopContext.currentProxy())
.getTargetSource()).swap(new Account(56, "dan"));


My custom target source

public class SwappableTargetSource implements TargetSource {

private Object target;

public SwappableTargetSource(Object initialTarget) { = initialTarget;

public synchronized Class<?> getTargetClass() {

public final boolean isStatic() {
return false;

public synchronized Object getTarget() {

public void releaseTarget(Object target) {
// nothing to do

public synchronized void swap(Object newTarget)
throws IllegalArgumentException { = newTarget;

public boolean equals(Object other) {
return (this == other || (other instanceof SwappableTargetSource &&
.equals(((SwappableTargetSource) other).target)));

public int hashCode() {
return SwappableTargetSource.class.hashCode();

public String toString() {
return "SwappableTargetSource for target: " +;


These are the spring xml configuration.

<bean id="accountDao" class="com.test.dao.account.AccountDAO">
<property name="advisor" ref="settersAdvisor" />

<bean id="swapableBeforeAdvice" class="com.test.framework.SwappableBeforeAdvice"/>

This is the advice which advise all setter methods on the bean

<bean id="settersAdvisor"
<property name="advice">
<ref local="swapableBeforeAdvice" />
<property name="patterns">

Thanks to this post in spring forum which helped me do this.

No comments:

Free Domain Names @!