Как ведут себя бины с разными scope (Singleton и Prototype) в Spring контексте?

«Как ведут себя бины с разными scope (Singleton и Prototype) в Spring контексте?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Поведение зависит от scope и контекста инъекции:

Singleton Scope (по умолчанию)

@Component
@Scope("singleton") // или без аннотации
public class SingletonBean {
    // Создается один раз при инициализации контекста
    // Один экземпляр на весь ApplicationContext
}

Prototype Scope

@Component
@Scope("prototype")
public class PrototypeBean {
    // Новый экземпляр при каждом запросе через:
    // - applicationContext.getBean()
    // - @Autowired в prototype бине
    // - Lookup method injection
}

Критически важный нюанс:

Когда Prototype бин инжектируется в Singleton бин:

@Component
public class SingletonService {
    @Autowired
    private PrototypeBean prototypeBean; // ИНИЦИАЛИЗИРУЕТСЯ ТОЛЬКО ОДИН РАЗ!
}

Почему так происходит:

  1. Singleton бин создается при старте контекста
  2. В момент создания происходит инъекция зависимостей
  3. Prototype бин создается один раз и "замораживается" в Singleton

Решение проблемы:

  1. Lookup Method Injection

    @Component
    @Scope("singleton")
    public abstract class SingletonService {
    @Lookup
    protected abstract PrototypeBean createPrototypeBean();
    
    public void process() {
        PrototypeBean bean = createPrototypeBean(); // Новый экземпляр каждый раз
    }
    }
  2. Использование ObjectFactory или Provider

    
    @Autowired
    private ObjectFactory<PrototypeBean> prototypeBeanFactory;

public void process() { PrototypeBean bean = prototypeBeanFactory.getObject(); // Новый экземпляр }


3. **Явный запрос из контекста**
```java
@Autowired
private ApplicationContext context;

public void process() {
    PrototypeBean bean = context.getBean(PrototypeBean.class);
}