Non-Singleton Bean Injected Into Singleton

ID

java.spring_non_singleton_bean_injected

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Java

Tags

best-practice, reliability, spring

Description

Reports an injection point in a singleton Spring bean — an @Autowired field, a parameter of a constructor Spring autowires, or a parameter of an @Autowired method — whose injected type carries a @Scope other than "singleton".

Rationale

Singleton beans, and everything they depend on, are built once when the application context starts. If a singleton keeps a reference to a bean with a shorter lifecycle — "prototype", "request", "session" — it holds onto that first instance forever instead of getting a new one on every request, session or lookup. The code reads as correct, but state that should reset per request instead leaks across every request that follows.

@Component
@Scope("prototype")
public class CartCalculator {
  private BigDecimal total = BigDecimal.ZERO;
  // ...
}

@Service
public class CheckoutService {

  @Autowired
  private CartCalculator calculator; // Bad: one CartCalculator for the whole application
}

Remediation

Defer the lookup to call time instead of injecting the dependency directly: ObjectFactory<T>, ObjectProvider<T>, Provider<T> (JSR-330) or the ApplicationContext all resolve a fresh instance on every call.

@Service
public class CheckoutService {

  private final ObjectFactory<CartCalculator> calculatorFactory;

  @Autowired
  public CheckoutService(ObjectFactory<CartCalculator> calculatorFactory) {
    this.calculatorFactory = calculatorFactory;
  }

  public void checkout() {
    CartCalculator calculator = calculatorFactory.getObject(); // Good: new instance per call
  }
}

© 2026 Xygeni. All rights reserved