gotchajavaspringMajor
Prototype-scoped bean injected into singleton behaves like a singleton
Viewed 0 times
prototype scopesingletonscoped proxyObjectProviderbean scopeproxyMode
Problem
A @Scope("prototype") bean injected into a @Singleton bean via constructor or field injection is only created once — at singleton creation time. All subsequent calls share the same prototype instance, defeating the purpose of the prototype scope.
Solution
Use a scoped proxy or inject the ApplicationContext and look up the bean programmatically:
// Option 1: scoped proxy (preferred)
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestState { ... }
// Option 2: ObjectFactory/Provider injection
@Service
public class OrderService {
private final ObjectProvider<RequestState> stateProvider;
public OrderService(ObjectProvider<RequestState> stateProvider) {
this.stateProvider = stateProvider;
}
public void handle() {
RequestState state = stateProvider.getObject(); // new instance each call
}
}Why
Spring resolves and injects beans at context startup. A prototype bean injected at that point is resolved once and stored. The singleton retains a direct reference to that single instance for its lifetime.
Gotchas
- ScopedProxyMode.TARGET_CLASS requires CGLIB on the classpath, which Spring Boot includes by default
- Scoped proxies add a layer of indirection — debugging may show a CGLIB proxy class instead of your class
- Request and session scopes have the same problem in singleton services; the same fix applies
Revisions (0)
No revisions yet.