Java EE 6 @ javax.annotation.ManagedBean vs. @ javax.inject.Named vs. @ javax.faces.ManagedBean


107

Java EE 6 spesifikasyonunda küçük bir karışıklık olduğunu hissediyorum. Birkaç ek açıklama grubu vardır.

Biz javax.ejbgibi ek açıklamaları @Statefulve @StatelessEJB'ler oluşturmak için.

Ayrıca @javax.annotation.ManagedBeanyönetilen bir fasulye oluşturmak için bir de var .

İçinde ek açıklamalar vardır javax.enterprise.contextgibi @SessionScopedve @RequestScoped.

Dahası, pakette @ManagedBeanve @SessionScoped/ @RequestScopedek açıklamalar da var javax.faces.bean.

Ve olayları daha karmaşık hale getirmek javax.injectiçin @Namedek açıklamalı bir paket var .

Biri lütfen birbirleriyle nasıl ilişkili olduklarını açıklayabilir mi?

Nerede kullanabilir @EJB, @Injectya da @ManagedProperydiğer fasulye enjekte etmek?


Yanıtlar:


194

Öncelikle bazı açıklamalar yapmama izin verin:

Yönetilen fasulye tanımı : genellikle yönetilen bir fasulye, yaşam döngüsünün (yapım, imha vb.) Bir kap tarafından yönetildiği bir nesnedir.

Java ee'de, JSF konteyneri, EJB konteyneri, CDI konteyneri, Servlet konteyneri vb. Gibi nesnelerinin yaşam döngüsünü yöneten birçok konteynere sahibiz.

Tüm bu kapsayıcılar bir tür bağımsız çalışır, uygulama sunucusu başlatmada önyüklenirler ve dağıtım zamanında jar, ejb-jar, war ve ear dosyaları dahil olmak üzere tüm yapıların sınıflarını tararlar ve bunlar hakkında bazı meta verileri toplar ve depolar, daha sonra bir nesneye ihtiyacınız olduğunda bir sınıfın çalışma zamanında size bu sınıfların örneklerini verecekler ve işi bitirdikten sonra onları yok edecekler.

Yani şunu söyleyebiliriz:

  • JSF yönetilen fasulye
  • CDI yönetilen fasulye
  • EJB yönetilen fasulye
  • Ve hatta Servlet'ler, bir servlet konteyneri olan bir konteyner tarafından başlatılıp yok edildikleri için yönetilen çekirdeklerdir.

Dolayısıyla, Managed Bean kelimesini gördüğünüzde, bağlamını veya türünü sormalısınız. (JSF, CDI, EJB vb.)

O zaman neden bu kapsayıcıların çoğuna sahip olduğumuzu sorabilirsiniz: AFAIK, Java EE çalışanları bir bağımlılık ekleme çerçevesine sahip olmak istediler, ancak tüm gereksinimleri tek bir spesifikasyonda toplayamadılar çünkü gelecekteki gereksinimleri tahmin edemediler ve EJB 1.0'ı yaptılar ve sonra 2.0 ve sonra 3.0 ve şimdi 3.1 ancak EJB'nin hedefi sadece bazı gereksinimler içindi (işlem, dağıtılmış bileşen modeli, vb.).

Aynı zamanda (paralel olarak) JSF'yi de desteklemeleri gerektiğini fark ettiler, ardından JSF tarafından yönetilen çekirdekler ve JSF çekirdekler için başka bir kap yaptılar ve bunu olgun bir DI kabı olarak gördüler, ancak yine de tam ve olgun bir kap değildi.

Bundan sonra Gavin King ve diğer bazı iyi adamlar;) gördüğüm en olgun DI konteyneri olan CDI yaptı. CDI (Seam2, Guice ve Spring'den esinlenerek) JSF ve EJB arasındaki boşluğu doldurmak için yapıldı ve pojo enjeksiyonu, yapımcı yöntemleri, durdurucular, dekoratörler, entegrasyon SPI, çok esnek vb. EJB ve JSF tarafından yönetilen çekirdekler ne yapıyor, o zaman sadece bir olgun ve güçlü DI kabına sahip olabiliriz. Ancak bazı geriye dönük uyumluluk ve politik nedenlerden dolayı Java EE çalışanları onları korumak istiyor !!!

Burada, bu türlerin her biri için farkı ve kullanım örneklerini bulabilirsiniz:

JSF Yönetilen Fasulye, CDI Fasulye ve EJB'ler

JSF, başlangıçta, JSF 2.0 için ek açıklama tabanlı çekirdekleri içerecek şekilde geliştirilmiş, kendi yönetilen çekirdek ve bağımlılık ekleme mekanizmasıyla geliştirildi. CDI, Java EE 6 ile piyasaya sürüldüğünde, bu platform için yönetilen çekirdek çerçevesi olarak görülüyordu ve elbette, EJB'ler on yıldan uzun süredir ortalıkta olmadıkları için bunların modasını geçmişti.

Sorun elbette hangisinin ne zaman kullanılacağını bilmektir.

JSF Tarafından Yönetilen en basit çekirdeklerle başlayalım.

JSF Yönetilen Fasulye

Kısacası, Java EE 6 için geliştiriyorsanız ve CDI kullanıyorsanız bunları kullanmayın. Bağımlılık enjeksiyonu için basit bir mekanizma sağlarlar ve web sayfaları için destek fasulyeleri tanımlarlar, ancak CDI çekirdeklerinden çok daha az güçlüdürler.

@javax.faces.bean.ManagedBeanİsteğe bağlı bir ad parametresi alan ek açıklama kullanılarak tanımlanabilirler . Bu ad, JSF sayfalarından fasulyeye referans vermek için kullanılabilir.

Kapsam, javax.faces.beanpakette tanımlanan , istek, oturum, uygulama, görünüm ve özel kapsamları içeren farklı kapsamlardan biri kullanılarak çekirdeğe uygulanabilir .

@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
    ....
    ....
}

JSF çekirdekleri, bir tür manuel kodlama yapılmadan diğer çekirdek türleriyle karıştırılamaz.

CDI Fasulye

CDI, Java EE 6'nın bir parçası olarak piyasaya sürülen çekirdek yönetimi ve bağımlılık ekleme çerçevesidir ve eksiksiz, kapsamlı bir yönetilen fasulye tesisi içerir. CDI çekirdekleri, JSF tarafından yönetilen basit çekirdeklerden çok daha gelişmiş ve esnektir. Önleyiciler, konuşma kapsamı, Olaylar, tip güvenli enjeksiyon, dekoratörler, klişeler ve yapımcı yöntemlerinden faydalanabilirler.

CDI çekirdeklerini dağıtmak için, fasulye.xml adlı bir dosyayı sınıf yolunda bir META-INF klasörüne yerleştirmelisiniz. Bunu yaptığınızda, paketteki her çekirdek bir CDI fasulyesi haline gelir. CDI'da pek çok özellik var, burada ele alınamayacak kadar çok, ancak JSF benzeri özellikler için hızlı bir referans olarak, javax.enterprise.contextpakette tanımlanan kapsamlardan birini (yani istek, konuşma) kullanarak CDI çekirdeğinin kapsamını tanımlayabilirsiniz. , oturum ve uygulama kapsamları). Bir JSF sayfasından CDI bean kullanmak istiyorsanız, javax.inject.Namednotu kullanarak ona bir isim verebilirsiniz . Bir fasulyeyi başka bir fasulyeye enjekte etmek için alana javax.inject.Injectnot ekliyorsunuz.

@Named("someBean")
@RequestScoped
public class SomeBean {

    @Inject
    private SomeService someService;
}

Yukarıda tanımlanan gibi otomatik enjeksiyon, enjekte edilmesini istediğiniz belirli sınıfla eşleşmeye yardımcı olabilecek Niteleyiciler kullanılarak kontrol edilebilir. Birden fazla ödeme türünüz varsa, eşzamansız olup olmadığı için bir niteleyici ekleyebilirsiniz. @NamedEk açıklamayı niteleyici olarak kullanabilseniz de , fasulyeleri EL'de göstermek için sağlandığı şekilde kullanmamalısınız.

CDI, vekillerin kullanımıyla uyumsuz kapsamlara sahip fasulye enjeksiyonunu gerçekleştirir. Bu nedenle, oturum kapsamlı bean'e istek kapsamlı bir bean enjekte edebilirsiniz ve referans, her istek için geçerli olmaya devam eder, çünkü her istek için proxy, istek kapsamlı bean'in canlı bir örneğine yeniden bağlanır.

CDI ayrıca, durdurucular, olaylar, yeni konuşma kapsamı ve JSF tarafından yönetilen çekirdeklere göre çok daha iyi bir seçim olmasını sağlayan diğer birçok özelliğe de sahiptir.

EJB

EJB'ler CDI çekirdeklerinden önce gelir ve bir şekilde CDI çekirdeklerine benzer ve diğer yönlerden çok farklıdır. Öncelikle, CDI çekirdekleri ve EJB'ler arasındaki fark, EJB'lerin şunlardır:

  • İşlemsel
  • Uzak veya yerel
  • Kaynakları serbest bırakan durum bilgili fasulyeleri pasifleştirebilme
  • Zamanlayıcıları kullanabilme
  • Eşzamansız olabilir

İki tür EJB'ye vatansız ve durum bilgili denir. Durum bilgisi olmayan EJB'ler, iki web isteği arasında herhangi bir durumu korumayan, iş parçacığı açısından güvenli tek kullanımlık çekirdekler olarak düşünülebilir. Durum bilgili EJB'ler durumu korurlar ve imha edilinceye kadar ihtiyaç duyuldukları sürece yaratılabilir ve etrafta oturabilirler.

Bir EJB'yi tanımlamak basittir, sınıfa bir javax.ejb.Statelessveya javax.ejb.Statefulnot eklemeniz yeterlidir.

@Stateless
public class BookingService {

  public String makeReservation(Item Item, Customer customer) {
    ...
    ...
  }
}

Durum bilgisi olmayan fasulye, bağımlı bir kapsama sahip olmalıdır, durum bilgisi olan bir oturum çekirdeği ise herhangi bir kapsama sahip olabilir. Varsayılan olarak bunlar işlemseldir, ancak işlem özniteliği ek açıklamasını kullanabilirsiniz.

EJB'ler ve CDI çekirdekleri özellikler açısından çok farklı olsa da, bunları entegre etmek için kod yazmak çok benzerdir çünkü CDI çekirdekleri EJB'lere enjekte edilebilir ve EJB'ler CDI çekirdeklerine enjekte edilebilir. Birini diğerine enjekte ederken herhangi bir ayrım yapmaya gerek yoktur. Yine, farklı kapsamlar, proxy kullanımıyla CDI tarafından ele alınır. Bunun bir istisnası, CDI'nın uzaktaki EJB'lerin enjeksiyonunu desteklememesidir, ancak bunun için basit bir üretici yöntemi yazarak uygulanabilir.

javax.inject.NamedGibi herhangi bir kalifiye olmuş EJB kullanılabilir açıklama bir enjeksiyon noktasına eşleşecek.

Hangi fasulyeyi ne zaman kullanmalı

Hangi fasulyeyi ne zaman kullanacağınızı nasıl anlarsınız? Basit.

Bir servlet kapsayıcısında çalışmıyorsanız ve Tomcat'te CDI çalıştırmayı denemek istemiyorsanız asla JSF tarafından yönetilen çekirdekleri kullanmayın (bunun için bazı Maven arketipleri olmasına rağmen hiçbir mazeret yoktur).

Genel olarak, işlemsel işlevler gibi EJB'lerde bulunan gelişmiş işlevselliğe ihtiyaç duymadığınız sürece, CDI fasulyelerini kullanmalısınız. CDI fasulyelerini işlemsel yapmak için kendi önleyicinizi yazabilirsiniz, ancak şimdilik, CDI hemen köşede olan işlemsel CDI fasulyelerini alana kadar bir EJB kullanmak daha kolaydır. Bir sunucu uygulaması kapsayıcısında sıkışmışsanız ve CDI kullanıyorsanız, EJB'ler olmadan elle yazılmış işlemler veya kendi işlem durdurucunuz tek seçenektir.

@ViewScopedCDI'da kullanmanız gerekiyorsa

  • kullanımı dikiş-yüzleri veya MyFaces CODI modülü. bunlardan birini sınıf yolunuza ekleyin ve CDI'da @ViewScopedçalışacaktır. MyFaces CODI, @ViewScoped için daha da sağlam bir desteğe sahiptir
  • MyFaces CODI'leri kullanın @ViewAccessScoped, bu Apache tarafından CDI üzerine yazılan bir uzantıdır, sadece indirin ve @ViewAccessScopedbunun yerine açıklama kullanın @ViewScoped.
  • CDI kullanın @ConversationScopedve uzun süre çalıştırın. Daha fazla bilgi için buraya bakın .
  • Omnifaces @ViewScoped açıklamasını kullanın

Buradan bazı parçalar çalındı .


3
Bu harika! Teşekkürler! Tamamlamak için, sadece CDI veya EJB fasulyesini JSF fasulyesine nasıl enjekte edeceğinizi söyleyin. Mı @ManagedProperty("#{someBean})"doğru yolu?
Piotr Gwiazda

2
Hayır! işe yaramayacak. CDI kullanarak açıklayarak fasulye yönetilen sadece jsf yönetilen fasulye açmak @Namedve @javax.enterprise.context.RequestScopedve kullanım CDI enjeksiyon @ Enjekte ek açıklama kullanarak. mecbur değilseniz jsf yönetimli fasulye kullanmayın;).
Mehdi

3
> JEE adamları onları korumak istiyor !!! - Bundan biraz daha incelikli. CDI, Java EE 6 döngüsünü oldukça geç bitirdi ve hem JSF 2 hem de JAX-RS zaten yapıldı. Gelişmiş yanıtları vardı. kendi yönetilen fasulye tesisini çoktan kurdular. CDI biraz daha önce mevcut olsaydı, işler farklı görünebilirdi. Java EE 7'de, JSF CDI'yi benimseyecek ve javax.faces.bean sonunda kullanımdan kaldırılacaktır (kullanımdan kaldırma, Java EE'de hem iyi hem de kötü olan yavaş bir süreçtir).
Arjan Tijms

3
CDI çekirdeklerini dağıtmak için, sınıf yolunda bir META-INF klasörüne fasulye.xml adlı bir dosya yerleştirmeniz gerekir. Bunu yaptığınızda, paketteki her çekirdek bir CDI fasulyesi haline gelir. Her fasulyenin, eskisine ek olarak bir CDI fasulyesi olduğunu mu söylüyorsunuz? ManagedBean ve ViewScoped ile JSF ManagedBeans'e sahipsem ne olur? Hala JSF Tarafından Yönetilen Fasulye, değil mi?
Koray Tugay

3
Birisi bu harika makalede Java EE 7 için güncelleme yapabilir mi?
Martijn Burger

7

Evet, bu kafa karıştırıcı olabilir.

Bazı ehm tarihsel nedenlerden ötürü, JSF ve CDI kapsamlar için aynı notları kullanıyor, ancak farklı paketlerden.

Muhtemelen tahmin ettiğiniz javax.faces.beangibi, bunların JSF spesifikasyonundandır ve CDI ile ilgili değildir. Bunu yapmak için çok iyi bir nedeniniz olmadıkça bunları kullanmayın. Ve bunları asla CDI ek açıklamalarıyla karıştırmayın javax.ejb. Bu, sonsuz sayıda böcek listesi ve ince anormallikler üretecektir.

Genel olarak mükemmel Kaynak dokümantasyonunun ilk birkaç (veya daha fazla) sayfasını gözden geçirmenizi tavsiye ederim . Bu sizi Java EE 6 için doğru yola sokacaktır.

Ve buraya daha fazla soru göndermekten çekinmeyin.


Aslında iki sorum var: 1. Genelde görüş alanını çok yararlı buluyorum. JSF ek açıklamalarını kullanmam gerekiyor mu? 2. @javax.annotation.ManagedBeanCDI tüm sınıflara yönetilen fasulye muamelesi yaptığından , bunun faydasız olduğu anlamına gelir, değil mi?
Piotr Gwiazda

Pek değil. JSF kapsamlarını, örneğin Dikiş Yüzleri ile CDI'ya köprülemeniz gerekecektir. Ve evet, ilgili jar dosyasında bir fasulye.xml varsa @ManagedBeans gerekli değildir. Oh, ve başka sorularınız varsa, yorum bölümünde kendimizi kaybetmeden önce yeni bir konuya başlamak daha iyidir.
jan groth

3

Özellikle hakkında hiçbir yanıt olmadığından @javax.annotation.ManagedBean, işte benzer bir sorunun cevabına bir bağlantı var: Fasulyeleri destekleme (@ManagedBean) veya CDI Fasulye (@Named)? . Spesifikasyon http://download.oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/ adresinde bulunabilir . Bana göre @javax.annotation.ManagedBeanbunun bir genellemesi olması gerekiyordu @javax.faces.bean.ManagedBean.

Anladığım kadarıyla, JSF Managed Beans, CDI Beans lehine aşamalı olarak kaldırılıyor (belki JSF 2.3'ten kaldırılıyor olabilir mi?), Bu yüzden sanırım @javax.annotation.ManagedBeanartık daha da eski hale geliyor.


@Namedgelecekte yerini alacak @ManagedBeanmı?
Thufir

1
CDI @Namedçekirdeklerinin JSF'nin yerini alacağını öngören farklı Java EE uzmanlarının birkaç ifadesini okudum @ManagedBeans, örneğin stackoverflow.com/questions/4347374/… , BalusC "Beklenti, @ManagedBean ve arkadaşlarının Java'ya göre kullanımdan kaldırılacağı yönündedir. EE 8. ".
Hein Blöd
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.