EJB 3.1 ve CDI nerede kullanılır?


120

GlassFish 3 ve EJB 3.1 kullandığım Java EE tabanlı bir ürün yapıyorum .

Uygulamamda oturum çekirdekleri , bir zamanlayıcı var ve web hizmetlerini kullanıyor. Yakın zamanda Contexts and Dependency Injection'ı (CDI) destekleyen Apache TomEE hakkında bilgi sahibi oldum . GlassFish kabı ayrıca CDI'yı da destekler.

CDI'nin zaten sağlamadığı herhangi bir özelliği gerektirmediğim durumlarda oturum fasulyelarını değiştirebilir miyim? Ve eğer öyleyse, elde edebileceğim faydalar nelerdir?

Yanıtlar:


409

Evet, hem CDI hem de EJB'yi özgürce karıştırabilir ve harika sonuçlar elde edebilirsiniz. Kullanıyormuşsunuz gibi görünüyor @WebServiceve @Schedulebunlar karışıma EJB eklemek için iyi nedenlerdir.

Orada çok fazla kafa karışıklığı var, bu yüzden burada EJB ve CDI hakkında birbirleriyle ilişkili olduklarından bazı genel bilgiler var.

EJB> = CDI

EJB'ler Not olduğunu vardır bu nedenle CDI fasulye ve CDI tüm avantajlarına sahip. Tersi (henüz) doğru değil. Bu nedenle, mantık gerçekten garip bir denklem olan "EJB + CDI vs CDI" anlamına geldiği için kesinlikle "EJB vs CDI" şeklinde düşünme alışkanlığı edinmeyin.

Java EE'nin gelecekteki sürümlerinde, bunları uyumlu hale getirmeye devam edeceğiz. Ne hizalama düzeneğinin sadece olmadan, insanlar zaten neler yapabileceğini yapmak için izin veriyor @Stateful, @Statelessya da @Singletonüstündeki ek açıklamadır.

Uygulama Koşullarında EJB ve CDI

Sonuçta, EJB ve CDI, proxy'li bileşenler olma temel tasarımını paylaşır. Bir EJB veya CDI fasulyesine referans aldığınızda, bu gerçek fasulye değildir. Aksine, size verilen nesne sahte (bir vekil). Bu sahte nesne üzerinde bir yöntem çağırdığınızda, çağrı, aramayı durdurucular, dekoratörler vb. Aracılığıyla gönderecek ve ayrıca herhangi bir işlem veya güvenlik kontrolüyle ilgilenecek konteynere gider. Tüm bunlar yapıldıktan sonra, çağrı nihayet gerçek nesneye gider ve sonuç proxy aracılığıyla arayana geri gönderilir.

Aradaki fark yalnızca çağrılacak nesnenin nasıl çözüldüğünde ortaya çıkar. "Çözüldü" ile basitçe, kapsayıcının çağırmak için gerçek örneği nerede ve nasıl aradığını kastediyoruz.

CDI'da kapsayıcı, temelde belirli bir süre (istek @RequestScopedbaşına, HTTP Oturumu @SessionScopedbaşına, uygulama başına @ApplicationScoped, JSF İletişimi @ConversationScopedveya özel kapsam uygulamanıza göre) yaşayan bir karma harita olacak bir "kapsam" içinde arar .

EJB'de, çekirdek türdeyse, kapsayıcı bir karma haritaya da bakar @Stateful. Bir @Statefulfasulye ayrıca, kapsamdaki diğer tüm çekirdeklerle birlikte yaşamasına ve ölmesine neden olan yukarıdaki kapsam ek açıklamalarından herhangi birini kullanabilir. EJB'de @Statefulesasen "herhangi bir kapsamlı" fasulyedir. @StatelessTemelde bir örnek havuzu - Bir çağırma süresince havuzundan bir örneğini olsun. @Singletonesasen@ApplicationScoped

Yani temel düzeyde, bir "EJB" fasulyesiyle yapabileceğiniz her şeyi bir "CDI" fasulyesi ile yapabilmelisiniz. Örtülerin altında onları birbirinden ayırmak çok zor. Örneklerin nasıl çözüldüğü dışında tüm su tesisatı aynıdır.

Konteynırın bu proxy'yi yaparken sunacağı hizmetler açısından şu anda aynı değiller, ancak söylediğim gibi bunun üzerinde Java EE özellik seviyesinde çalışıyoruz.

Performans notu

Sahip olabileceğiniz "hafif" veya "ağır" zihinsel görüntülere aldırmayın. Hepsi pazarlama. Çoğunlukla aynı iç tasarıma sahiptirler. CDI örnek çözünürlüğü belki biraz daha karmaşıktır çünkü biraz daha dinamik ve bağlamsaldır. EJB örnek çözünürlüğü, kıyaslandığında oldukça statik, aptal ve basittir.

Size TomEE'deki bir uygulama perspektifinden söyleyebilirim, bir EJB'yi çağırmakla bir CDI çekirdeğini çağırmak arasında sıfır performans farkı var.

Varsayılan olarak POJO'lar, ardından CDI, ardından EJB

Elbette hiçbir faydası olmadığında CDI veya EJB kullanmayın. Enjeksiyon, olaylar, önleyiciler, dekoratörler, yaşam döngüsü takibi ve benzeri şeyler istemeye başladığınızda CDI ekleyin. Çoğu zaman bu.

Bu özelliklerinin dışında, kullanışlı konteyner hizmetleri bir numara size CDI da fasulye ekleyerek EJB yaparsanız sadece kullanma seçeneğine sahip bulunmaktadır @Stateful, @Statelessya @Singletonbuna.

İşte EJB'leri ne zaman kırdığımın kısa bir listesi.

JAX-WS'yi kullanma

Bir JAX-WS'yi açığa çıkarmak @WebService. Tembelim. Aynı @WebServicezamanda bir EJB olduğunda, onu listelemeniz ve web.xmldosyada sunucu uygulaması olarak eşleştirmeniz gerekmez . Bu benim için iş. Ayrıca, aşağıda belirtilen diğer işlevlerden herhangi birini kullanma seçeneğine de sahip oluyorum. Bu yüzden benim için hiç düşünmeden.

Yalnızca @Statelessve @Singletonyalnızca kullanılabilir.

JAX-RS kullanımı

Aracılığıyla bir JAX-RS kaynağını açığa çıkarma @Path. Hâlâ tembelim. RESTful hizmeti de bir EJB olduğunda, yine otomatik keşif alırsınız ve bunu bir JAX-RS Applicationalt sınıfına veya buna benzer bir şeye eklemeniz gerekmez . Ayrıca, @WebServiceaşağıda belirtilen harika işlevlerden herhangi birini kullanmak istersem veya kullanmak istersem, aynı fasulyenin aynısını gösterebilirim .

Yalnızca @Statelessve @Singletonyalnızca kullanılabilir.

Başlangıç ​​mantığı

Başlangıçta yükle @Startup. Şu anda CDI'da buna eşdeğer bir şey yok. Her nasılsa AfterStartupkapsayıcı yaşam döngüsüne bir olay gibi bir şey eklemeyi kaçırdık . @ApplicationScopedBunu yapsaydık, onu dinleyen bir fasulyeye sahip olabilirdiniz ve bu, bir @Singletonile ile aynı şey olurdu @Startup. CDI 1.1 listesinde.

Uygun @Singletonyalnızca.

Paralelde Çalışma

@Asynchronousyöntem çağrısı. Herhangi bir sunucu tarafı ortamında iş parçacığı başlatmak bir hayırdır. Çok fazla iş parçacığına sahip olmak ciddi bir performans katilidir. Bu açıklama, kapsayıcının iş parçacığı havuzunu kullanarak yaptığınız şeyleri paralelleştirmenize olanak tanır. Bu harika.

Uygun @Stateful, @Statelessve @Singleton.

İş planlama

@Scheduleveya ScheduleExpressiontemelde bir cron veya Quartzişlevselliktir. Ayrıca çok harika. Çoğu kap, bunun için kapakların altında sadece Quartz kullanır. Ancak çoğu insan, Java EE'de planlama işinin işlemsel olduğunu bilmiyor! Bir veritabanını günceller ve ardından bazı işler planlarsanız ve bunlardan biri başarısız olursa, her ikisi de otomatik olarak temizlenir. Eğer EntityManagerdevam çağrısı başarısız veya bir sorun yıkama var, iş un-zamanlamaya gerek yoktur. Yaşasın, işlemler.

Yalnızca @Statelessve @Singletonyalnızca kullanılabilir.

EntityManager'ları bir JTA işleminde kullanma

İşlemlerle ilgili yukarıdaki not elbette bir JTAyönetilen kullanmanızı gerektirir EntityManager. Bunları düz "CDI" ile kullanabilirsiniz, ancak konteyner tarafından yönetilen işlemler olmadan UserTransactionkesinleştirme / geri alma mantığını çoğaltarak gerçekten monoton hale gelebilir .

CDI, JSF dahil tüm Java EE bileşenlerine Temin @ManagedBean, @WebServlet, @WebListener, @WebFilter, vb @TransactionAttributeaçıklama, ancak, kullanılabilir @Stateful, @Statelessve @Singletonsadece.

JTA'nın yönetilmesini sağlamak EntityManager

EXTENDEDYönetilen EntityManagerbir saklamanızı sağlar EntityManagerarasındaki açık JTAişlemler ve kaybetmek önbelleğe alınmış verileri. Doğru zaman ve yer için iyi bir özellik. Sorumlu kullanın :)

Uygun @Statefulyalnızca.

Kolay senkronizasyon

Senkronizasyona ihtiyacınız olduğunda, @Lock(READ)ve @Lock(WRITE)ek açıklamalar oldukça mükemmel. Eşzamanlı erişim yönetimini ücretsiz olarak almanızı sağlar. Tüm ReentrantReadWriteLock tesisatlarını atlayın. Aynı pakette, @AccessTimeoutvazgeçmeden önce bir iş parçacığının fasulye örneğine erişmek için ne kadar beklemesi gerektiğini söylemenize olanak tanır.

Sadece @Singletonfasulyelerde mevcuttur.


32
Tanrı aşkına David :) Sanırım bunu hallettin.
LightGuard

7
Bu cevap için teşekkür ederim. Kafamdaki tıkanıklığı temizledin ve birçok noktayı birleştirdin.
Thupten

7
Bu, bu konuyla ilgili şimdiye kadar okuduğum en iyi açıklama. Aynı zamanda, Gerçek Hayatta kullanımda EJB'nin neredeyse tüm önemli yönlerini de kapsar. Harika iş!!
nanoquack

3
Çok anlaşılır ve Adam katı yasal terimlerle yanlış değil, ancak ayrım tartışmalı. Spesifikasyon, EJB örneğinin bağlamsal olmadığını söylüyor, ancak daha sonra EJB'ye yapılan başvurunun (proxy) bağlamsal olduğunu söylüyor. Durum bilgili bir fasulyenin yaşam döngüsü tamamen referans (proxy) aracılığıyla kontrol edilir, bu nedenle CDI konteyneri bu referansı (vekil) kontrol ettiğinde matematik aynı şekilde çıkar - Durum bilgili EJB'ler etkin bir şekilde bağlamsal olabilir.
David Blevins

3
Bunu TESLA'daki öğle yemeği molasında mı yazdın?
Edison

2

ejb 3.1'in herhangi bir özelliğini gerçekten kullanmıyorsanız, cevap basittir. ama tahmin edin, sorularınız farkında olmadan faydalandığınız ejb 3.1 kavramları olduğundan şüphelendiğinizi gösteriyor. bir örnek, konteynerin kullanıma hazır bir slsb havuzunu tutabilmesi, böylece jms ve veritabanı bağlantılarının isteğin bir parçası olarak enjekte edilmesine gerek kalmaması olabilir.

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.