As we all know, the self-invokation of bean's method is not working in Spring without AspectJ.
See this question for example.
I think this is because the Spring-created proxy calls the target object's methods using delagate pattern. Like this:
class MyClass {
@Autowired
private MyClass self; // actually a MyProxy instance
@Transactional // or any other proxy magic
public void myMethod() {}
public void myOtherMethod() {
this.myMethod(); // or self.myMethod() to avoid self-invokation problem
}
}
class MyProxy extends MyClass { // or implements MyInterface if proxyMode is not TARGET_CLASS and MyClass also implements MyInterface
private final MyClass delegate;
@Override
public void myMethod() {
// some proxy magic: caching, transaction management etc
delegate.myMethod();
// some proxy magic: caching, transaction management etc
}
@Override
public void myOtherMethod() {
delegate.myOtherMethod();
}
}
Am I right?
With this code:
public void myOtherMethod() {
this.myMethod();
}
this.myMethod()
will bypass the proxy (so all @Transactional
or @Cacheable
magic) because it is just internal delegate's call... So we should inject a MyClass
bean (which is actually is MyProxy
instance) inside MyClass
and call self.myMethod()
instead. It is understandable.
But why the proxy is implemented this way?
Why it is not just extends the target class, overriding all public methods and calling super
instead of delegate
?
Like this:
class MyProxy extends MyClass {
// private final MyClass delegate; // no delegate
@Override
public void myMethod() {
// some proxy magic: caching, transaction management etc
super.myMethod();
// some proxy magic: caching, transaction management etc
}
@Override
public void myOtherMethod() {
super.myOtherMethod();
}
}
It should solve the self-invokation problem, where this.myMethod()
bypasses the proxy, because in this case this.myMethod()
, invoked from MyClass.myOtherMethod()
(we remember that MyClass bean actually is MyProxy instance), will invoke overriden child's method (MyProxy.myMethod()
).
So, my main question is why it is not implemented this way?