Em primeiro lugar, deixe-me fazer alguns esclarecimentos:
Definição de bean gerenciado : geralmente um bean gerenciado é um objeto cujo ciclo de vida (construção, destruição, etc.) é gerenciado por um contêiner.
Em Java ee temos muitos containers que gerenciam o ciclo de vida de seus objetos, como container JSF, container EJB, container CDI, container Servlet, etc.
Todos esses contêineres funcionam de forma independente, eles inicializam na inicialização do servidor de aplicativos e examinam as classes de todos os artefatos, incluindo jar, ejb-jar, war e arquivos ear em tempo de implantação e reúnem e armazenam alguns metadados sobre eles, então quando você precisa de um objeto de uma classe em tempo de execução, eles fornecerão instâncias dessas classes e, após terminar o trabalho, eles as destruirão.
Portanto, podemos dizer que temos:
- Feijões gerenciados JSF
- Feijão gerenciado CDI
- Feijões gerenciados EJB
- E mesmo Servlets são beans gerenciados porque são instanciados e destruídos por um contêiner, que é um contêiner de servlet.
Portanto, quando você vir a palavra Managed Bean, deve perguntar sobre o contexto ou tipo dela. (JSF, CDI, EJB, etc.)
Então você pode perguntar por que temos muitos desses contêineres: AFAIK, os caras do Java EE queriam ter uma estrutura de injeção de dependência, mas não conseguiram reunir todos os requisitos em uma especificação porque não podiam prever os requisitos futuros e criaram EJB 1.0 e então 2.0 e depois 3.0 e agora 3.1, mas o objetivo do EJB era apenas para alguns requisitos (transação, modelo de componente distribuído, etc).
Ao mesmo tempo (em paralelo), eles perceberam que precisavam oferecer suporte ao JSF também, então eles fizeram beans gerenciados JSF e outro contêiner para os beans JSF e o consideraram um contêiner DI maduro, mas ainda não era um contêiner completo e maduro.
Depois disso, Gavin King e alguns outros caras legais;) fizeram CDI, que é o contêiner de DI mais maduro que já vi. CDI (inspirado em Seam2, Guice e Spring) foi feito para preencher a lacuna entre JSF e EJB e muitas outras coisas úteis como injeção de pojo, métodos de produção, interceptores, decoradores, integração SPI, muito flexível, etc. e pode até fazer o que os beans gerenciados EJB e JSF estão fazendo, então podemos ter apenas um contêiner de DI maduro e poderoso. Mas por alguma compatibilidade com versões anteriores e razões políticas, os caras do Java EE querem mantê-los !!!
Aqui você pode encontrar a diferença e os casos de uso para cada um desses tipos:
JSF Managed Beans, CDI Beans e EJBs
O JSF foi inicialmente desenvolvido com seu próprio bean gerenciado e mecanismo de injeção de dependência que foi aprimorado para JSF 2.0 para incluir beans baseados em anotação. Quando o CDI foi lançado com o Java EE 6, era considerado o framework de bean gerenciado para aquela plataforma e, claro, os EJBs os desatualizaram, já que existem há mais de uma década.
O problema, claro, é saber qual usar e quando usá-los.
Vamos começar com os beans gerenciados JSF mais simples.
JSF Managed Beans
Resumindo, não os use se estiver desenvolvendo para Java EE 6 e usando CDI. Eles fornecem um mecanismo simples para injeção de dependência e definição de beans de apoio para páginas da web, mas são muito menos poderosos do que os beans CDI.
Eles podem ser definidos usando a @javax.faces.bean.ManagedBean
anotação que leva um parâmetro de nome opcional. Este nome pode ser usado para fazer referência ao bean a partir das páginas JSF.
O escopo pode ser aplicado ao bean usando um dos diferentes escopos definidos no javax.faces.bean
pacote, que incluem a solicitação, sessão, aplicativo, visualização e escopos personalizados.
@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
....
....
}
Os beans JSF não podem ser misturados com outros tipos de beans sem algum tipo de codificação manual.
Feijão CDI
CDI é a estrutura de gerenciamento de bean e injeção de dependência que foi lançada como parte do Java EE 6 e inclui um recurso de bean gerenciado completo e abrangente. Os beans CDI são muito mais avançados e flexíveis do que os beans gerenciados JSF simples. Eles podem fazer uso de interceptores, escopo de conversação, eventos, injeção de segurança de tipo, decoradores, estereótipos e métodos produtores.
Para implementar os beans CDI, você deve colocar um arquivo chamado beans.xml em uma pasta META-INF no classpath. Depois de fazer isso, cada bean no pacote se torna um bean CDI. Existem muitos recursos no CDI, muitos para cobrir aqui, mas como uma referência rápida para recursos do tipo JSF, você pode definir o escopo do bean CDI usando um dos escopos definidos no javax.enterprise.context
pacote (ou seja, solicitação, conversação , sessão e escopos de aplicativo). Se quiser usar o bean CDI de uma página JSF, você pode dar um nome a ele usando a javax.inject.Named
anotação. Para injetar um bean em outro bean, você anota o campo com javax.inject.Inject
anotação.
@Named("someBean")
@RequestScoped
public class SomeBean {
@Inject
private SomeService someService;
}
A injeção automática como a definida acima pode ser controlada através do uso de qualificadores que podem ajudar a combinar a classe específica que você deseja injetar. Se você tiver vários tipos de pagamento, poderá adicionar um qualificador para saber se é assíncrono ou não. Embora você possa usar a @Named
anotação como um qualificador, não deveria, pois ela é fornecida para expor os beans em EL.
O CDI lida com a injeção de beans com escopos incompatíveis por meio do uso de proxies. Por causa disso, você pode injetar um bean com escopo de solicitação em um bean com escopo de sessão e a referência ainda será válida em cada solicitação porque, para cada solicitação, o proxy se reconecta a uma instância ativa do bean com escopo de solicitação.
O CDI também tem suporte para interceptores, eventos, o novo escopo de conversação e muitos outros recursos que o tornam uma escolha muito melhor em relação aos beans gerenciados JSF.
EJB
Os EJBs são anteriores aos beans CDI e, de alguma forma, são semelhantes aos beans CDI e, de outras maneiras, muito diferentes. Primeiramente, as diferenças entre os beans CDI e EJBs é que os EJBs são:
- Transacional
- Remoto ou local
- Capaz de passivar beans com estado, liberando recursos
- Capaz de fazer uso de temporizadores
- Pode ser assíncrono
Os dois tipos de EJBs são chamados de stateless e stateful. EJBs sem estado podem ser considerados como beans de uso único thread-safe que não mantêm nenhum estado entre duas solicitações da web. EJBs com estado mantêm o estado e podem ser criados e permanecer em funcionamento pelo tempo que forem necessários até que sejam descartados.
Definir um EJB é simples, basta adicionar uma anotação javax.ejb.Stateless
ou javax.ejb.Stateful
à classe.
@Stateless
public class BookingService {
public String makeReservation(Item Item, Customer customer) {
...
...
}
}
Os beans sem estado devem ter um escopo dependente, enquanto um bean de sessão com estado pode ter qualquer escopo. Por padrão, eles são transacionais, mas você pode usar a anotação de atributo de transação.
Embora os EJBs e os beans CDI sejam muito diferentes em termos de recursos, escrever o código para integrá-los é muito semelhante, já que os beans CDI podem ser injetados em EJBs e os EJBs podem ser injetados em beans CDI. Não há necessidade de fazer qualquer distinção ao injetar um no outro. Novamente, os diferentes escopos são tratados pelo CDI por meio do proxy. Uma exceção a isso é que o CDI não oferece suporte à injeção de EJBs remotos, mas isso pode ser implementado escrevendo um método de produtor simples para ele.
A javax.inject.Named
anotação, bem como quaisquer qualificadores, podem ser usados em um EJB para combiná-lo com um ponto de injeção.
Quando usar qual feijão
Como saber quando usar qual bean? Simples.
Nunca use beans gerenciados JSF, a menos que esteja trabalhando em um contêiner de servlet e não queira tentar fazer o CDI funcionar no Tomcat (embora haja alguns arquétipos Maven para isso, então não há desculpa).
Em geral, você deve usar os beans CDI, a menos que precise da funcionalidade avançada disponível nos EJBs, como funções transacionais. Você pode escrever seu próprio interceptor para tornar os beans CDI transacionais, mas, por enquanto, é mais simples usar um EJB até que o CDI obtenha os beans CDI transacionais que estão logo ali. Se você estiver preso em um contêiner de servlet e estiver usando CDI, as transações escritas à mão ou seu próprio interceptor de transação são a única opção sem EJBs.
Se você precisa usar @ViewScoped
em CDI, você deve
- usar seam-faces ou módulo CODI MyFaces . apenas adicione um deles ao seu classpath e
@ViewScoped
funcionará no CDI. MyFaces CODI tem um suporte ainda mais sólido de @ViewScoped
- use MyFaces CODI's
@ViewAccessScoped
, é uma extensão escrita em cima do CDI pelo Apache, basta fazer o download e usar @ViewAccessScoped
anotação em vez de @ViewScoped
.
- Use o CDI
@ConversationScoped
e torne-o de longa duração. Veja aqui para mais informações .
- Use a anotação Omnifaces @ViewScoped
Algumas peças roubadas daqui .