Short answer
A singleton is wired once at creation, so the prototype is resolved exactly once and that single instance is captured for the lifetime of the singleton, defeating the prototype scope.
Explanation
The clean fix is to inject ObjectProvider<MyProtoBean> (or jakarta Provider) and call getObject() per use, which asks the container for a fresh instance each time. Alternatives are method injection via @Lookup, or a scoped proxy; injecting ApplicationContext and calling getBean works but reintroduces the service-locator smell.
Common mistakes
- Expecting a prototype injected into a singleton to be new each call.
- Not knowing ObjectProvider, lookup methods or scoped proxies fix it.