Ответ
В Spring scope (область видимости) "prototype" означает, что контейнер создает новый экземпляр бина при каждом запросе (через getBean() или инъекцию зависимости). Это противоположность scope "singleton" (по умолчанию), где контейнер возвращает один и тот же экземпляр.
Когда использовать:
- Когда состояние бина не должно разделяться между разными частями приложения.
- Для stateful-бинов (содержащих изменяемое состояние, специфичное для клиента).
- Когда бин не является потокобезопасным и используется в многопоточной среде.
Пример объявления prototype-бина:
-
С помощью аннотации
@Scope:import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @Component @Scope("prototype") // Ключевая аннотация public class PrototypeService { private int id = (int) (Math.random() * 1000); // Уникальное состояние для каждого экземпляра public int getId() { return id; } } -
В XML-конфигурации:
<bean id="prototypeService" class="com.example.PrototypeService" scope="prototype"/>
Пример использования и проверки:
@RestController
public class TestController {
// При каждой инъекции будет создан НОВЫЙ экземпляр PrototypeService
@Autowired
private PrototypeService service1;
@Autowired
private PrototypeService service2;
@GetMapping("/test")
public String test() {
// service1 и service2 — разные объекты с разными id
return "Service1 ID: " + service1.getId() +
", Service2 ID: " + service2.getId();
// Вывод будет примерно: "Service1 ID: 742, Service2 ID: 319"
}
}
Важные замечания:
- Spring не управляет полным жизненным циклом prototype-бинов после их создания и передачи клиенту. Метод уничтожения (
@PreDestroy) не будет вызван контейнером. - Использование prototype для всех бинов может негативно сказаться на производительности из-за постоянного создания объектов.
- Для внедрения prototype-бина в singleton-бин часто используется режим инъекции
Lookup MethodилиProvider<>, чтобы избежать фиксации одного экземпляра.