Is possible to get the proxy of a given object in Spring? I need to call a function of a subclass. But, obviously, when I do a direct call, the aspects aren't applied. Here's an example:
public class Parent {
public doSomething() {
Parent proxyOfMe = Spring.getProxyOfMe(this); // (please)
Method method = this.class.getMethod("sayHello");
method.invoke(proxyOfMe);
}
}
public class Child extends Parent {
@Secured("president")
public void sayHello() {
System.out.println("Hello Mr. President");
}
}
I've found a way of achieving this. It works, but I think is not very elegant:
public class Parent implements BeanNameAware {
@Autowired private ApplicationContext applicationContext;
private String beanName; // Getter
public doSomething() {
Parent proxyOfMe = applicationContext.getBean(beanName, Parent.class);
Method method = this.class.getMethod("sayHello");
method.invoke(proxyOfMe);
}
}
AopContext.currentProxy()
as suggested by Tomasz will work. A more generic solution, that will work outside of the proxied class is to cast the object toorg.springframework.aop.framework.Advised
and get.getTargetSource().getTarget()
The former (getting the real object from the proxied object) is something that you should not really need. On the other hand getting the target proxy might be useful in some utility class that inspects existing beans in order to add some feature.
This hack is extremely awkward, please consider refactoring your code or using AspectJ weaving. You may feel warned, here is the solution
JavaDoc. I blogged about it here and here.
You can use a bean post-processor to set a reference to the proxy on the target bean. It moves the Spring-specifics from your beans to a single class.
Post-Processor
Context
Register the post-processor in
applicationContext.xml
.Beans
Each bean must implement
SelfReferencingBean
to tell the post-processor that it needs a reference to the proxy.Now implement
setProxy
in each bean that needs to call itself through its proxy.You could put this last bit of code into a bean base class if you don't mind casting
proxy
to bean's type when calling methods directly on it. Since you're going throughMethod.invoke
you wouldn't even need the cast.With a little work I bet this could be converted to an annotation processor a la
@Autowired
. Come to think of it, I don't recall if I even tried adding a self-reference using@Autowired
itself.