Qual é a diferença entre os escopos @ApplicationScoped e @Singleton no CDI?

92

No CDI existe o pseudo-escopo @ApplicationScopede o ( javax.inject) @Singleton. Qual a diferença entre eles? Além do fato de que @ApplicationScopedé procurado, e @Singletonnão é.

Posso apenas mudar meu @Singletonfeijão para @ApplicationScoped? O @ApplicationScopedbean pode ter duas (ou mais) instâncias?

amorfis
fonte
11
Você leu a referência do Weld ? Há alguma explicação sobre as diferenças práticas entre @ApplicationScopede @Singletonem sua seção 5.4 (p. 36).
brandizzi
3
Eu também acho o resumo das diferenças no final deste artigo germanescobar.net/2010/04/… útil
matt freake
1
qual escopo Singleton você está se referindo - javax.ejb ou javax.inject?
John Ament de

Respostas:

29

@Singletonnão faz parte da especificação CDI. Faz parte do EJB e javax.inject(JSR-330). Não é mencionado na especificação qual é o seu comportamento, então você só pode confiar no que está escrito na documentação do Weld.

Bozho
fonte
11
Isso não é verdade. Existe a anotação javax.inject.Singleton. Faz parte do CDI. Verifique aqui: docs.jboss.org/weld/reference/1.0.1-Final/en-US/html_single/…
amorfis
5
@amorphis - eu tenho a especificação CDI na minha frente. Eu até implementei partes dele, e não menciona nada sobre @Singleton. É mostrado em apenas um exemplo, sem esclarecimentos. É verdade que o CDI depende javax.inject, mas, estritamente falando, não faz parte das especificações do CDI. Dito isso, corrigi um pouco minha resposta.
Bozho
17

Resumindo: você pode até misturar ( @Singletone @ApplicationScoped) e faz sentido em alguns cenários. (e funciona conforme o esperado no meu!)

Além das outras respostas até agora, gostaria de adicionar mais alguns pontos para esclarecimento em cenários do mundo real.

Para mim, esta questão foi desenvolvida a partir de Como faço para forçar um bean com escopo de aplicativo a instanciar na inicialização do aplicativo? Em alguma discussão lá eu afirmei isso e não consigo encontrar um argumento válido contra isso até agora:

Em muitos cenários / configurações da vida real, eu diria que é difícil dizer definitivamente - de um ponto de vista abstrato / de modelagem - se algo é (ou se tornará / será tratado como) um EJB ou um bean gerenciado com escopo de aplicativo.

argumentos (discutíveis, mas não conclusivos) (do meu ponto de vista) contra isso até agora: (@BalusC e todos os outros: eu gostaria de vê-los sendo conclusivos, mas se não, o acima pode ser verdadeiro e, no entanto, os argumentos podem ainda ajuda o leitor a entender as diferenças / vantagens / desvantagens / más / boas práticas)

EJB vs. Managed Bean

BalusC : Esse é um EJB, não um bean gerenciado, o que é bem diferente. Os EJBs são executados no back-end e os beans gerenciados no front-end. Os EJBs também são executados no contexto transacional. [...] Você acabou de confundir enterprise beans com managed beans e eu apenas apontei isso.

mas:

eu : Acho que você não está totalmente correto e exagerando o significado / uso e isso me parece questionável. http://en.wikipedia.org/wiki/Enterprise_JavaBeans

Enterprise JavaBeans (EJB) é um software de servidor gerenciado para construção modular de software corporativo e uma das várias APIs Java. EJB é um componente de software do lado do servidor que encapsula a lógica de negócios de um aplicativo.

Tipos de Enterprise Beans

Beans de sessão [3] que podem ser "Stateful", "Stateless" ou "Singleton" [...]

Feijões movidos por mensagem [...]

... o que ainda é verdade no meu caso.

Singleton EJB vs. Bean com escopo de aplicativo

Trancando

BalusC : Um EJB singleton não é o mesmo que um bean com escopo de aplicativo. Um EJB singleton é bloqueado para leitura / gravação e, portanto, potencialmente ineficiente / superconvoluído para a tarefa que você tinha em mente. Resumindo: pegue um bom livro Java EE e aprenda a usar a ferramenta certa para o trabalho. Uma maneira definitivamente não é a outra. O fato de funcionar não significa que seja a ferramenta certa. Uma marreta é capaz de prender um parafuso, mas não é necessariamente a ferramenta certa para isso :)

mas:

(Não consigo ver a marreta aqui - desculpe ...) É bom saber os padrões de bloqueio (eu não estava ciente disso), mas isso parece estar incorreto novamente: Tutorial do Oracle Java EE 6 sobre gerenciamento de acesso simultâneo em um Feijão de Sessão Singleton

Ao criar um único bean de sessão, o acesso simultâneo aos métodos de negócios do singleton pode ser controlado de duas maneiras: simultaneidade gerenciada por contêiner e simultânea gerenciada por bean. [...]

Embora, por padrão, os singletons usem simultaneidade gerenciada por contêiner, a anotação @ConcurrencyManagement (CONTAINER) pode ser adicionada no nível de classe do singleton para definir explicitamente o tipo de gerenciamento de simultaneidade

Andreas Dietrich
fonte
Weld não se diverte misturando: Exceção ao carregar o aplicativo: Falha de definição de CDI: WELD-000046: No máximo um escopo pode ser especificado em [EnhancedAnnotatedTypeImpl] public ApplicationScoped Singleton MyClass. Usando javax.inject.Singleton.
sgflt
10

Normalmente, quando você deseja ter apenas uma instância de algum objeto, você provavelmente deve usar a @ApplicationScopedanotação - tal objeto é proxy e, portanto, pode até ser serializado corretamente fora da caixa.

Por outro lado, também há muitos casos em que você deseja apenas uma instância da classe, mas essa classe não pode ser representada por proxy (por exemplo, por ser final) - então @Singletoné um resgate. Porque Singletoné um pseudo-escopo e não está sendo proxy como qualquer escopo "normal".

G. Demecki
fonte
Estou rejeitando isso porque não está muito claro. Estou programando em Java EE há cinco anos, fazendo tutoriais e lendo livros, mas não tenho uma ideia clara do que você quer dizer quando diz "tal objeto é proxy", "pode ​​até ser serializado corretamente" e "pseudo- escopo". Eu adoraria saber o que significa isso, pois parece que você sabe do que está falando, mas como está escrito, não posso imaginar que sua resposta ajude a maioria dos desenvolvedores Java EE.
DavidS
2
Dito isso, eu sei que os EJBs têm proxy. Minha confusão é parcialmente em torno da distinção que você está fazendo para os solteiros.
DavidS
9

@Singletonem JSR-299 refere-se a beans de sessão Singleton ( javax.ejb.Singletone não javax.inject.Singleton), não a beans gerenciados JSR-299 em um escopo integrado chamado Singleton.

Você pode descobrir em seu servidor que @ApplicationScopedé um por EAR ou um por WAR / EJB-JAR, pois não está claro na especificação, mas definitivamente não deve esperar que seja um por JVM.

covener
fonte
7

Há mais uma diferença: @Singletonnão é um bean definindo anotações, pois o Singletonescopo não é um escopo normal. Então, o @ApplicationScopedbean define as anotações.

Com a especificação CDI 1.1: Quando o aplicativo está no modo de descoberta = anotado, o Weld não identifica os beans com @Singletone não carrega este

vigor
fonte
2

Uma das principais diferenças que você pode escrever sua classe com o construtor padrão tem um modificador de acesso privado ao usar javax.inject.Singleton, mas sua classe deve ter um construtor padrão com pelo menos o modificador de acesso padrão ao usar javax.enterprise.context.ApplicationScopede esta é a JBOSS 6.1 GA Finalimplementação

user1017344
fonte
Você quis dizer “construtor padrão”?
Treefish Zhang