Apa perbedaan antara cakupan @ApplicationScoped dan @Singleton di CDI?

96

Di CDI ada pseudo-scope @ApplicationScopeddan ( javax.inject) @Singleton. Apa perbedaan di antara keduanya? Selain fakta yang @ApplicationScopeddiproksikan, dan @Singletontidak.

Bisakah saya mengubah @Singletonkacang saya menjadi @ApplicationScoped? Bisakah @ApplicationScopedkacang memiliki dua (atau lebih) contoh?

amorfis
sumber
12
Sudahkah Anda membaca referensi Weld ? Ada beberapa penjelasan tentang perbedaan praktis antara @ApplicationScopeddan @Singletonpada bagian 5.4 (hlm. 36).
brandizzi
1
cakupan Singleton mana yang Anda maksud - javax.ejb atau javax.inject?
John Ament

Jawaban:

30

@Singletonbukan bagian dari spesifikasi CDI. Ini adalah bagian dari EJB dan javax.inject(JSR-330). Tidak disebutkan dalam spesifikasi apa perilakunya, jadi Anda hanya dapat mengandalkan apa yang tertulis dalam dokumentasi Weld.

Bozho
sumber
11
Itu tidak benar. Ada penjelasan javax.inject.Singleton. Ini adalah bagian dari CDI. Periksa di sini: docs.jboss.org/weld/reference/1.0.1-Final/en-US/html_single/…
amorfis
5
@ amamorphis - Saya memiliki spesifikasi CDI di depan saya. Saya bahkan telah menerapkan sebagian darinya, dan itu tidak menyebutkan apa-apa @Singleton. Ini ditunjukkan hanya dalam satu contoh, tanpa klarifikasi. Memang benar bahwa CDI bergantung javax.inject, tetapi secara tegas itu bukan bagian dari spesifikasi CDI. Meski begitu, saya mengoreksi jawaban saya sedikit.
Bozho
17

singkatnya: Anda bahkan dapat mencampurnya ( @Singletondan @ApplicationScoped) dan itu masuk akal dalam beberapa skenario. (dan bekerja seperti yang diharapkan di milik saya!)

Selain jawaban lain sejauh ini, saya ingin menambahkan beberapa poin lagi untuk klarifikasi dalam skenario dunia nyata.

Bagi saya, pertanyaan ini dikembangkan dari Bagaimana cara memaksa kacang bercakupan aplikasi untuk dipakai saat startup aplikasi? Dalam beberapa diskusi di sana saya menyatakan ini dan sejauh ini tidak dapat menemukan argumen yang valid untuk menentangnya:

Dalam banyak skenario / pengaturan kehidupan nyata, saya akan mengatakan sulit untuk mengatakan dengan pasti - dari sudut pandang abstrak / pemodelan - apakah sesuatu itu (atau akan menjadi / diperlakukan seperti) EJB atau kacang yang dikelola dengan cakupan aplikasi.

Argumen (bisa diperdebatkan tetapi tidak konklusif) (dari sudut pandang saya) yang menentangnya sejauh ini: (@BalusC dan lainnya: Saya ingin melihat mereka menjadi konklusif, tetapi jika tidak, hal di atas mungkin benar dan meskipun demikian argumennya mungkin tetap membantu pembaca untuk mendapatkan perbedaan / kelebihan / kekurangan / buruk / praktik yang baik)

EJB vs. Kacang Terkelola

BalusC : Itu adalah EJB bukan kacang yang dikelola, yang sangat berbeda. EJB berjalan di backend dan mengatur kacang di frontend. EJB juga berjalan dalam konteks transaksional. [...] Anda hanya bingung kacang perusahaan dengan kacang terkelola dan saya baru saja menunjukkannya.

tapi:

saya : Saya pikir Anda kurang tepat dan melebih-lebihkan arti / penggunaan dan itu terlihat bisa diperdebatkan bagi saya. http://en.wikipedia.org/wiki/Enterprise_JavaBeans

Enterprise JavaBeans (EJB) adalah perangkat lunak server terkelola untuk konstruksi modular perangkat lunak perusahaan, dan salah satu dari beberapa API Java. EJB adalah komponen perangkat lunak sisi server yang merangkum logika bisnis aplikasi.

Jenis Kacang Perusahaan

Kacang Sesi [3] yang dapat berupa "Stateful", "Stateless" atau "Singleton" [...]

Kacang Berbasis Pesan [...]

... yang masih berlaku dalam kasus saya.

Singleton EJB vs. Application Scoped Bean

Mengunci

BalusC : EJB tunggal tidak sama dengan kacang cakupan aplikasi. Sebuah EJB tunggal dibaca / tulis terkunci dan dengan demikian berpotensi tidak efisien / terlalu berbelit-belit untuk tugas yang ada dalam pikiran Anda. Singkat cerita: Dapatkan buku Java EE yang bagus dan pelajari cara menggunakan alat yang tepat untuk pekerjaan itu. Satu cara pasti bukan sebaliknya. Berhasil tidak berarti itu alat yang tepat. Palu godam mampu mengencangkan sekrup, tetapi itu belum tentu alat yang tepat untuk itu :)

tapi:

(Saya tidak bisa melihat palu godam di sini - maaf ...) Ada baiknya mengetahui default penguncian (saya tidak menyadarinya), tetapi ini tampaknya salah lagi: Tutorial Oracle Java EE 6 tentang Mengelola Akses Bersamaan di a Singleton Session Bean

Saat membuat kacang sesi tunggal, akses bersamaan ke metode bisnis tunggal dapat dikontrol dengan dua cara: konkurensi yang dikelola kontainer dan konkurensi yang dikelola kacang. [...]

Meskipun secara default, lajang menggunakan konkurensi yang dikelola kontainer, anotasi @ConcurrencyManagement (PENAMPUNG) dapat ditambahkan pada tingkat kelas tunggal untuk secara eksplisit menyetel jenis manajemen konkurensi

Andreas Dietrich
sumber
Weld tidak terhibur oleh pencampuran: Pengecualian saat memuat aplikasi: Definisi CDI gagal: WELD-000046: Paling banyak satu ruang lingkup dapat ditentukan pada [EnhancedAnnotatedTypeImpl] public ApplicationScoped Singleton MyClass. Menggunakan javax.inject.Singleton.
sgflt
12

Biasanya ketika Anda ingin memiliki hanya satu contoh dari beberapa objek, Anda mungkin harus menggunakan @ApplicationScopedanotasi - objek seperti itu diproksikan dan dengan demikian bahkan dapat diserialkan dengan benar di luar kotak.

Di sisi lain, ada juga banyak kasus, di mana Anda hanya menginginkan satu instance kelas, tetapi kelas tersebut tidak dapat diproksikan (misalnya karena sudah final) - maka itu @Singletonadalah penyelamatan. Karena Singletonmerupakan lingkup semu dan tidak sedang diproksikan seperti lingkup "normal" lainnya.

G. Demecki
sumber
Saya tidak mendukung ini karena sangat tidak jelas. Saya telah membuat kode di Java EE selama lima tahun, mengikuti tutorial, dan membaca buku, tetapi saya tidak mengerti apa yang Anda maksud ketika Anda mengatakan "objek seperti itu diproksikan", "bahkan dapat diserialkan dengan benar", dan "pseudo- cakupan". Saya ingin tahu apa yang dimaksud dengan ini, karena sepertinya Anda tahu apa yang Anda bicarakan, tetapi saat ada tertulis, saya tidak dapat membayangkan jawaban Anda akan membantu sebagian besar pengembang Java EE.
DavidS
2
Karena itu, saya tahu EJB di-proxy-kan. Kebingungan saya sebagian ada pada perbedaan yang Anda buat untuk Singletons.
DavidS
9

@Singletondi JSR-299 mengacu pada kacang sesi Singleton ( javax.ejb.Singleton, bukan javax.inject.Singleton), bukan kacang yang dikelola JSR-299 dalam lingkup built-in yang disebut Singleton.

Anda mungkin menemukan di server Anda bahwa @ApplicationScopedsatu-per EAR atau satu-per WAR / EJB-JAR karena tidak jelas dalam spesifikasinya, tetapi Anda seharusnya tidak mengharapkannya menjadi satu per JVM.

covener
sumber
7

Ada satu perbedaan lagi: @Singletonbukan anotasi yang mendefinisikan kacang, karena Singletoncakupannya bukan cakupan normal. Kemudian @ApplicationScopedadalah penjelasan yang mendefinisikan kacang.

Dengan spesifikasi CDI 1.1: Ketika aplikasi dalam mode penemuan = dianotasi, Weld tidak mengidentifikasi kacang dengan @Singletondan tidak memuat ini

semangat
sumber
2

Salah satu perbedaan utama bahwa Anda dapat menulis kelas Anda dengan konstruktor default memiliki pengubah akses pribadi saat menggunakan javax.inject.Singleton, tetapi kelas Anda harus memiliki konstruktor default dengan setidaknya pengubah akses default saat menggunakan javax.enterprise.context.ApplicationScopeddan ini adalah JBOSS 6.1 GA Finalimplementasi

pengguna1017344
sumber
Apakah maksud Anda "konstruktor default"?
Treefish Zhang