Когда использовать прототип Spring?
Я хочу знать, когда я должен использовать prototype
сфера весной? Я поняла что singleton
возвращает тот же экземпляр объекта, если запрошен компонент.
Тогда почему мы должны рассмотреть prototype
?
Пояснения с примерами очень помогли бы понять необходимость этого.
4 ответа
Чтобы были понятны простые определения:
Область действия прототипа = новый объект создается каждый раз, когда он вводится / просматривается. Будет использовать новый
SomeBean()
каждый раз.Singleton scope = Один и тот же объект возвращается каждый раз, когда он вводится / просматривается. Здесь будет создан один экземпляр
SomeBean
и затем возвращайте его каждый раз.
Бин-прототип создается во время использования. Поэтому, когда вы хотите иметь bean-компоненты statefull, иногда возникает необходимость иметь область действия прототипов или когда вы не хотите кэшировать какие-либо значения в bean-компонентах. Бин-прототип может быть связан с одним сеансом или некоторым вызовом.
Пример:
Объект доступа к данным (DAO) обычно не настроен в качестве прототипа, потому что типичный DAO не содержит никакого диалогового состояния; этому автору было проще использовать ядро синглтон-диаграммы.
Есть несколько интересных вариантов использования: используя прототип области видимости, вы создадите более качественную и надежную конструкцию / архитектуру приложения, например систему реального времени.
Представьте, что вы должны построить систему отслеживания транспортных средств в режиме реального времени, и у вас будет 2 000 000 автомобилей, которые будут обмениваться информацией каждые 5 секунд. Со стороны сервера вы будете работать с двумя или более различными группами конфигураций, одна для автомобилей, а другая один для грузовиков.
Основываясь на этом простом примере, если вы спроектируете свое приложение для работы с различными группами конфигурации в памяти посредством шаблона прототипа, вы достигнете лучшей производительности.
Таким образом, в этом случае, всякий раз, когда сервер получает новое сообщение от Truck, например, сервер получит экземпляр конфигурации в памяти из хэш-карты экземпляров VehicleGrupConfiguration, а затем применит поведение конфигурации, которое должно иметь это сообщение, например: как тайм-аут, повторите... и т. д.
Я хотел бы подчеркнуть, что существует множество способов реализации этой ситуации, но этот пример показывает, что шаблон прототипа очень силен в вопросах производительности и шаблонов проектирования.
Как сказано в документации, создание bean-компонента Foo с областью видимости прототипа аналогично вызову:
Foo foo = new Foo(dependency1, dependency2, ...);
foo.initialize(dependency7, dependency8...);
Единственная веская причина использовать компонент области видимости прототипа вместо new
это когда зависимости, используемые для создания и инициализации экземпляра, должны храниться вне кода, которому нужен новый экземпляр.
Например, если вы хотите написать код сохранения состояния, аналогичный EJB2 Java Entity beans, например
Person p = ...
p.setName("John Doe");
p.save(); // write to DB
Вместо использования способа JPA
Person p = new Person();
p.setName("John Doe");
personService.save(p); // write to DB
В стиле кода entity-компонента экземпляр человека должен знать, как он должен сохраняться, поэтому в него необходимо добавить детали сохранения, о которых человек, пишущий код, не должен знать.
Другой пример: если вы хотите использовать небезопасный для потоков Java-класс SimpleDateFormat во многих местах вашего приложения с шаблоном формата из файла конфигурации (возможно, используя разные форматы в зависимости от других условий). Вместо того, чтобы создавать новый экземпляр формата во всех этих местах, загружая также строку форматирования из файла (или свойства spring), вы можете использовать область прототипа, чтобы каждый раз получать новый экземпляр, при этом детали установки общего формата находятся в одном место.
Компоненты с областью действия прототипа полезны для сервисов, которые выполняют более длительные или ресурсоемкие операции и не нуждаются в сохранении состояния при нескольких вызовах методов. Создание нового экземпляра компонента для каждого вызова метода гарантирует, что ресурсы не будут распределяться между несколькими запросами и что каждый запрос будет обрабатываться независимо от других. Это может помочь избежать потенциальных проблем параллелизма и повысить производительность.
С другой стороны, одноэлементные bean-компоненты полезны для сервисов, которые выполняют короткие и быстрые операции, или для сервисов, которым необходимо поддерживать состояние при нескольких вызовах методов. Используя один экземпляр компонента, состояние можно поддерживать при вызовах методов и избежать накладных расходов на создание нового экземпляра для каждого вызова метода.
В общем, важно выбрать подходящую область действия компонента, исходя из конкретных потребностей службы. Если сервису требуется общее состояние для нескольких вызовов методов или он должен быть легковесным и эффективным, обычно лучшим выбором будет одноэлементная область. Однако если служба работает долго, требует ресурсов или ее необходимо изолировать от нескольких запросов, область прототипа обычно является лучшим выбором.
Пример:
Допустим, у вас есть приложение, которое генерирует отчеты на основе вводимых пользователем данных. Для каждого отчета требуются разные наборы данных, и его создание занимает много времени. Вы хотите избежать создания отчета несколько раз, если пользователь хочет снова увидеть тот же отчет.
В этом случае для создания каждого отчета можно использовать компонент с областью действия прототипа. Когда пользователь запрашивает отчет, вы создаете новый экземпляр генератора отчетов, генерируете отчет и возвращаете отчет пользователю. Таким образом, если пользователь снова запросит тот же отчет, будет создан новый экземпляр генератора отчетов, гарантируя, что отчет будет создан заново и не будет использоваться повторно.
Если мы используем область прототипа bean-компонента для bean-компонента PDFGenerator, новый экземпляр bean-компонента будет создаваться каждый раз, когда делается запрос на создание PDF-файла. Это полезно, поскольку создание PDF-файлов может быть ресурсоемкой операцией, требующей времени, и мы не хотим связывать наши ресурсы путем одновременного создания нескольких PDF-файлов с использованием одного и того же экземпляра bean-компонента. Каждый запрос PDF-файла будет обрабатываться отдельным экземпляром bean-компонента PDFGenerator, поэтому ресурсы не будут распределяться между несколькими запросами.
Если бы мы использовали область действия одноэлементного компонента для bean-компонента PDFGenerator, при запуске приложения был бы создан только один экземпляр bean-компонента. Это означает, что если несколько пользователей попытаются одновременно создать PDF-файлы, они будут использовать для этого один и тот же экземпляр bean-компонента PDFGenerator. Это потенциально может привести к конкуренции за ресурсы, поскольку несколько пользователей конкурируют за один и тот же ресурс. Кроме того, если процесс создания PDF-файла у одного пользователя занимает много времени, это может привести к задержке запросов других пользователей.
В этом сценарии использование прототипа области bean-компонента является лучшим выбором, поскольку оно гарантирует, что каждый запрос PDF-файла обрабатывается независимо от других и что ресурсы не распределяются между несколькими запросами. Создавая новый экземпляр bean-компонента PDFGenerator для каждого запроса, мы избегаем потенциальных проблем параллелизма и повышаем производительность.