В чем разница между областями @ApplicationScoped и @Singleton в CDI?

96

В CDI есть псевдо-область видимости @ApplicationScopedи ( javax.inject) @Singleton. В чем разница между ними? Помимо того, что @ApplicationScopedпроксируется, и @Singletonнет.

Могу я просто поменять свой @Singletonbean на @ApplicationScoped? Может ли @ApplicationScopedbean иметь два (или более) экземпляра?

Аморфис
источник
12
Вы читали ссылку на Weld ? Есть некоторое объяснение практических различий между @ApplicationScopedи @Singletonв разделе 5.4 (стр. 36).
brandizzi
1
о какой области Singleton вы имеете в виду - javax.ejb или javax.inject?
Джон Эмент

Ответы:

30

@Singletonне является частью спецификации CDI. Это часть EJB и javax.inject(JSR-330). В спецификации не упоминается, каково его поведение, поэтому вы можете полагаться только на то, что написано в документации Weld.

Божо
источник
11
Это не правда. Есть аннотация javax.inject.Singleton. Это часть CDI. Проверьте здесь: docs.jboss.org/weld/reference/1.0.1-Final/en-US/html_single/…
Amorfis
5
@amorphis - Передо мной спецификация CDI. Я даже реализовал его части, и в нем ничего не упоминается @Singleton. Это показано только на одном примере без пояснений. Это правда, что CDI полагается javax.inject, но, строго говоря, это не часть спецификации CDI. Тем не менее, я немного поправил свой ответ.
Божо
17

вкратце: вы даже можете смешивать это ( @Singletonи @ApplicationScoped), и это имеет смысл в некоторых сценариях. (и работает как положено в моем!)

В дополнение к другим ответам я хотел бы добавить еще несколько моментов для пояснения в реальных сценариях.

Для меня этот вопрос возник из статьи « Как заставить bean-компонент с областью действия приложения создавать экземпляр при запуске приложения?» В некоторой дискуссии я заявил об этом и пока не могу найти веского аргумента против этого:

Во многих реальных сценариях / установках я бы сказал, что трудно однозначно сказать - с абстрактной точки зрения / точки зрения моделирования - является ли что-то (или станет / будет рассматриваться как) EJB или управляемый компонент с областью действия приложения.

(спорные, но не окончательные) аргументы (с моей точки зрения) против этого до сих пор: (@BalusC и все другие: я бы хотел, чтобы они были убедительными, но если нет, то приведенное выше может быть верным, и тем не менее аргументы могут по-прежнему помогают читателю понять различия / преимущества / недостатки / плохие / хорошие практики)

EJB против управляемого компонента

BalusC : Это EJB, а не управляемый компонент, что совсем другое. EJB-компоненты запускаются в бэкэнде, а управляемые бины - во внешнем интерфейсе. EJB-компоненты также работают в транзакционном контексте. [...] Вы просто перепутали корпоративные компоненты с управляемыми компонентами, и я только что указал на это.

но:

Я : Я думаю, что вы не совсем правы и переоцениваете значение / использование, и мне это кажется спорным. http://en.wikipedia.org/wiki/Enterprise_JavaBeans

Enterprise JavaBeans (EJB) - это управляемое серверное программное обеспечение для модульного построения корпоративного программного обеспечения и один из нескольких Java API. EJB - это программный компонент на стороне сервера, который инкапсулирует бизнес-логику приложения.

Типы корпоративных бинов

Сессионные бины [3], которые могут иметь статус "Stateful", "Stateless" или "Singleton" [...]

Бины, управляемые сообщениями [...]

... что все еще верно в моем случае.

Singleton EJB против компонента с областью действия приложения

Блокировка

BalusC : Singleton EJB - это не то же самое, что bean-компонент с областью действия приложения. Одноэлементный EJB заблокирован для чтения / записи и, следовательно, потенциально неэффективен / чрезмерно свернут для задачи, которую вы имели в виду. Короче говоря: возьмите хорошую книгу по Java EE и научитесь использовать правильный инструмент для работы. Один способ определенно не является другим. То, что это работает, не означает, что это правильный инструмент. Кувалда способна прикрутить винт, но это не обязательно подходящий инструмент :)

но:

(Я не вижу здесь кувалду - извините ...) Хорошо знать значения блокировки по умолчанию (я не знал об этом), но это снова кажется неверным: Oracle Java EE 6 Tutorial on Managing Concurrent Access in a Сессионный компонент Singleton

При создании одноэлементного сеансового компонента параллельный доступ к бизнес-методам одноэлементного объекта можно контролировать двумя способами: параллелизм, управляемый контейнером, и параллелизм, управляемый компонентом. [...]

Хотя по умолчанию синглтоны используют управляемый контейнером параллелизм, аннотация @ConcurrencyManagement (CONTAINER) может быть добавлена ​​на уровне класса синглтона, чтобы явно установить тип управления параллелизмом.

Андреас Дитрих
источник
Уэлда не забавляет смешивание: Исключение при загрузке приложения: Ошибка определения CDI: WELD-000046: В [EnhancedAnnotatedTypeImpl] общедоступный Singleton MyClass ApplicationScoped может быть указана не более одной области. Использование javax.inject.Singleton.
sgflt
12

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

С другой стороны, также есть много случаев, когда вам нужен только один экземпляр класса, но такой класс не может быть проксирован (например, из-за того, что он окончательный) - тогда @Singletonэто спасение. Потому Singletonчто это псевдо-область видимости и не проксируется, как любая "нормальная" область видимости.

Г. Демеки
источник
Я голосую против, потому что это очень непонятно. Я программировал на Java EE пять лет, брал уроки и читал книги, но я не понимаю, что вы имеете в виду, когда говорите «такой объект проксируется», «может быть даже правильно сериализован» и «псевдо- объем". Я хотел бы знать, что имеется в виду под этим, поскольку похоже, что вы знаете, о чем говорите, но, поскольку это написано, я не могу представить, что ваш ответ поможет большинству разработчиков Java EE.
DavidS
2
Тем не менее, я знаю, что EJB проксируются. Мое замешательство частично связано с различием, которое вы делаете для синглтонов.
DavidS
9

@Singletonв JSR-299 относится к сеансовым компонентам Singleton ( javax.ejb.Singletonне javax.inject.Singleton), а не к управляемым компонентам JSR-299 во встроенной области, называемой Singleton.

Вы можете найти на своем сервере @ApplicationScopedодин на EAR или один на WAR / EJB-JAR, поскольку это не ясно в спецификации, но вы определенно не должны ожидать, что это будет один на JVM.

завещатель
источник
7

Есть еще одно отличие: @Singletonкомпонент не определяет аннотации, так как Singletonобласть видимости не является нормальной областью. Затем @ApplicationScoped- аннотации, определяющие компонент.

Согласно спецификации CDI 1.1: когда приложение находится в режиме обнаружения = аннотировано, Weld не идентифицирует bean-компоненты @Singletonи не загружает их

сила
источник
2

Одно из основных различий в том, что вы можете написать свой класс с конструктором по умолчанию, имеет модификатор частного доступа при использовании javax.inject.Singleton, но ваш класс должен иметь конструктор по умолчанию с как минимум модификатором доступа по умолчанию при использовании, javax.enterprise.context.ApplicationScopedи это JBOSS 6.1 GA Finalреализация

user1017344
источник
Вы имели в виду «конструктор по умолчанию»?
Treefish Чжан