Although our colleagues have provided correct answers, I'll summarize.
When it comes to aspects implementation, spring generates a proxy that wraps your controller. The proxy is implemented in a way that it has special hooks to invoke aspects before and after the class (or around, altering the flow altogether).
Spring uses two different strategies for proxy generation:
- java.lang.Proxy based
- CGLIB based
The first one is in general better, faster but works only with interfaces. The generated proxy is "something" that implements all the methods of the interface. The implementation methods contain those hooks I've talked before, but since the methods are only methods in the interface they have to be public
CGLIB - is slower, but it can work with classes as well (with some restrictions though). The way it works is sub-classing the parent class and overriding the methods provided by the super class. This new method (let's call it foo) will call all the hooks and somewhere in code if needed will call super.foo()
.
Now, obviously this can't really work with private methods because its impossible to override private methods.
That's why my colleagues have pointed that private
won't work here.
Now regarding the self injection stuff:
When you're inside the method of original controller and you're trying to call just another method (even if its public), you're not working with proxy any more, you're kind of behind the proxy and work with original class. So this means that you won't be able to take advantage of "enhanced" method.
That's why there is a self injection - you can see (with debugger for example) that the self-injected dependency is actually a dependency with all the proxies, that's why it starts to work.
Another workaround is to refactor the method to another Spring bean, inject this bean to your controller, and provide a definition for that bean.