0

Когда использовать прототипный скоуп в Spring?

15

Я хочу понять, когда именно следует использовать область видимости <code>prototype</code> в Spring. Я понял, что <code>singleton</code> возвращает один и тот же экземпляр объекта, если запрашивается бин.

Почему тогда стоит рассматривать использование <code>prototype</code>?

Примеры с пояснениями значительно помогли бы лучше осознать необходимость в этом варианте.

4 ответ(ов)

0

Чтобы прояснить, вот простые определения:

  • Прототипный scope (prototype scope) = Каждый раз при инъекции или запросе создаётся новый объект. При этом будет использоваться new SomeBean() каждый раз.
  • Синглтонный scope (singleton scope) = Один и тот же объект возвращается каждый раз при инъекции или запросе. Здесь будет создана лишь одна инстанция SomeBean, которая затем будет возвращаться при каждой инъекции.

Бин прототипного scope создаётся в момент его использования. Таким образом, когда вам нужны состояния в бинах (stateful beans), действительно может возникнуть необходимость использовать прототипный scope, или если вы не хотите кэшировать значения в бинах. Прототипный бин может быть связан с одной сессией или конкретным вызовом.

Пример:

Объект доступа к данным (DAO) обычно не настраивается как прототип, поскольку типичный DAO не хранит никакого состояния, связанного с сеансом (conversational state); автору просто было удобнее переиспользовать основную часть диаграммы синглтона.

0

Использование скоупа prototype может значительно улучшить архитектуру и надежность вашего приложения, особенно в случаях с реальными системами.

Представьте, что вам необходимо создать систему для отслеживания автомобилей в реальном времени, где 2.000.000 машин обмениваются данными каждые 5 секунд. На стороне сервера вы будете работать с двумя или более различными группами конфигураций — одна для легковых автомобилей и другая для грузовиков.

На основе этого простого примера, если вы спроектируете ваше приложение таким образом, чтобы оно работало с отдельными группами конфигураций в памяти, используя паттерн прототипа, вы сможете достичь лучшей производительности.

В данном случае, когда сервер получает новое сообщение от грузовика, он получает экземпляр конфигурации из оперативной памяти, обращаясь к хэш-карте экземпляров VehicleGroupConfiguration, и затем применяет поведение конфигурации, соответствующее этому сообщению, например: таймаут, повторная попытка и т.д.

Важно отметить, что существует множество способов реализации данной ситуации, но этот пример показывает, что паттерн прототипа очень эффективен с точки зрения производительности и проектирования.

0

Как указано в документации, создание бина Foo с областью видимости prototype эквивалентно следующему коду:

Foo foo = new Foo(dependency1, dependency2, ...);
foo.initialize(dependency7, dependency8...);

Одной из основных причин использования бина с областью видимости prototype вместо создания нового экземпляра с помощью оператора new является необходимость сохранить зависимости, используемые для создания и инициализации экземпляра, вне кода, который нуждается в новом экземпляре.

Рассмотрим пример:

// В этом случае нам нужно явно указать зависимости
public void createdWithNew(Dependency dependency1, Dependency dependency2) {
  Foo foo = new Foo(dependency1, dependency2, ...);
  foo.doSomething();
}

// Зависимости управляются в классе Foo с помощью Spring
public void createdWithSpring(Foo foo) {
  foo.doSomething();
}

Пример использования — вы хотите написать код для работы с хранилищем, подобный Java Entity beans в EJB2, например:

Person p = ...
p.setName("John Doe");
p.save(); // записать в БД

Вместо использования подхода JPA:

Person p = new Person();
p.setName("John Doe");
personService.save(p); // записать в БД

В стиле кода с entity bean экземпляр Person должен знать, как он должен храниться, и поэтому ему нужно внедрение деталей хранения, о которых код, создающий экземпляр Person, не должен знать.

Другой пример: Если вы хотите использовать нест thread-safe класс SimpleDateFormat в различных местах вашего приложения с шаблоном формата из конфигурационного файла (возможно, используя разные форматы в зависимости от других условий), вместо того, чтобы создавать новый экземпляр формата во всех этих местах, загружая также строку формата из файла (или свойств Spring), вы можете использовать область видимости prototype, чтобы получать новый экземпляр каждый раз, при этом детали настройки общего формата находятся в одном месте.

0

Вопрос: В чем разница между использованием бинов с прототипной и синглтон-областью?

Ответ: Бины с прототипной областью полезны для сервисов, которые выполняют длительные или ресурсоемкие операции и не требуют сохранения состояния между вызовами методов. Создание нового экземпляра бина для каждого вызова метода гарантирует, что ресурсы не будут разделяться между несколькими запросами, а каждый запрос будет обрабатываться независимо от других. Это помогает избежать потенциальных проблем с конкурентностью и улучшить производительность.

С другой стороны, бины с синглтоновской областью подходят для сервисов с быстрыми операциями или для тех, которые нуждаются в сохранении состояния между вызовами методов. Используя единственный экземпляр бина, можно поддерживать состояние между вызовами и избегать накладных расходов на создание нового экземпляра для каждого вызова метода.

В общем, важно правильно выбирать область бина в зависимости от конкретных потребностей сервиса. Если сервис требует общего состояния между вызовами методов или должен быть легковесным и эффективным, лучше всего подойдет синглтон. Однако, если сервис требует длительных или ресурсоемких операций, или должен быть изолированным для каждого запроса, лучше использовать прототипную область.

Пример:

Представьте, что у вас есть приложение, которое генерирует отчеты на основе пользовательских вводов. Каждый отчет требует разных наборов данных и занимает много времени для генерации. Вы хотите избежать повторной генерации отчета, если пользователь снова запросит тот же отчет.

В этом случае вы можете использовать бин с прототипной областью для генерации каждого отчета. Когда пользователь запрашивает отчет, вы создаете новый экземпляр генератора отчетов, генерируете отчет и возвращаете его пользователю. Таким образом, если пользователь снова запросит тот же отчет, будет создан новый экземпляр генератора отчетов, что гарантирует, что отчет будет сгенерирован заново, а не переиспользован.

Если мы используем прототипную область для бина PDFGenerator, то каждый раз при запросе на генерацию PDF-файла будет создаваться новый экземпляр бина. Это полезно, потому что генерация PDF может быть ресурсоемкой операцией, и мы не хотим нагружать ресурсы, генерируя несколько PDF-файлов одновременно с использованием одного и того же экземпляра бина. Каждый запрос на PDF-файл будет обрабатываться отдельным экземпляром бина PDFGenerator, благодаря чему ресурсы не будут разделяться между несколькими запросами.

Если бы мы использовали синглтон для бина PDFGenerator, то только один экземпляр бина был бы создан при запуске приложения. Это значит, что если несколько пользователей пытаются сгенерировать PDF-файлы одновременно, они будут использовать один и тот же экземпляр бина PDFGenerator. Это может привести к конфликтам ресурсов, когда несколько пользователей конкурируют за один и тот же ресурс. Кроме того, если процесс генерации PDF для одного из пользователей занимает много времени, это может задерживать запросы других пользователей.

В данной ситуации использование прототипной области бина является более предпочтительным выбором, так как это гарантирует, что каждый запрос на PDF-файл будет обрабатываться независимо от других и ресурсы не будут разделяться между несколькими запросами. Создавая новый экземпляр бина PDFGenerator для каждого запроса, мы избегаем потенциальных проблем с конкурентностью и улучшаем производительность.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь