The solution I found is to use org.springframework.aop.aspectj.annotation.AspectJProxyFactory
.
An added complication in my case is that the class I want to proxy is abstract, not an interface, meaning Spring must proxy it with CGLIB and not a JDK proxy. However, this proved in a way to be more useful than it is annoying.
First, I have an abstract class:
public abstract class Something {
abstract void doWhatever();
@Override
public final boolean equals(Object o) {
return this == o;
}
@Override
public final int hashCode() {
return System.identityHashCode(this);
}
@Override
public final String toString() {
return getClass().getName() + " " + hashCode();
}
}
(I've overridden some Object methods and made them final
because they would otherwise be proxied, but in that case I would need to write Advice for them.)
Then I have an AspectJProxyFactory
and a bean with prototype scope as such:
@Configuration
@EnableAspectJAutoProxy
class Config {
private static final AspectJProxyFactory proxyFactory = new AspectJProxyFactory();
static {
proxyFactory.setTargetClass(Something.class);
proxyFactory.addAspect(SomeAspect.class);
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
Something something() {
return proxyFactory.getProxy();
}
}
Note that the Something
s must be beans for Spring AOP to be made aware of them. And this is the Aspect:
@Aspect
public class SomeAspect {
@Around("execution(void org.luc.Something.doWhatever())")
void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println(pjp.getThis().toString() + ": I've been advised");
}
}
This way I can get distinct instances from the proxy factory, which will have been advised by the AOP auto-proxy.
Something something1 = applicationContext.getBean(Something.class);
Something something2 = applicationContext.getBean(Something.class);
Assert.assertEquals(something1, something1);
Assert.assertNotEquals(something1, something2);
something1.doWhatever();
something2.doWhatever();
This prints something like:
org.luc.Something$$EnhancerBySpringCGLIB$$cadae9a8 638486177: I've been advised
org.luc.Something$$EnhancerBySpringCGLIB$$cadae9a8 426019904: I've been advised