This behavior which looks helpful at first glance, is very confusing. If your not proficient with Spring or spend hours reading the documentation you'll never understand that: 1. Your object lifetime is tied to the request. 2. The instance you see at the debugger is actually a subclass that redirects all call to the actual scoped object instance depending on a thread local variable (I guess?) 3. The proxy instance is either slow (JDK Proxy) or could cause you grief when you upgrade to the next version of Java (CGLIB). It's not clear which is which without some investigating.
I rather prefer to go with a lightweight framework + a sane DI framework and do something more explicit, e.g. create a RequestProvider<T> interface:
interface RequestProvider<T> {
get(request: Request): T
}
class MyController() {
val fooProvider: RequestProvider<Foo> by inject(name = "foo")
fun myHandler(request: Request) {
val requestScopedFoo = fooProvider.get(request)
}
}
This approach is more explicit, but I prefer it.