Perbedaan Antara CDI dan EJB Singleton

1. Ikhtisar

Dalam tutorial ini, kita akan melihat lebih dekat pada dua jenis lajang yang tersedia di Jakarta EE. Kami akan menjelaskan dan mendemonstrasikan perbedaan dan melihat penggunaan yang sesuai untuk masing-masing.

Pertama, mari kita lihat apa itu lajang sebelum masuk ke detailnya.

2. Pola Desain Singleton

Ingatlah bahwa cara umum untuk mengimplementasikan Pola Singleton adalah dengan instance statis dan konstruktor pribadi:

public final class Singleton { private static final Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } } 

Tapi, sayangnya, ini tidak benar-benar berorientasi objek. Dan itu memiliki beberapa masalah multi-threading.

Kontainer CDI dan EJB memberi kita alternatif berorientasi objek.

3. CDI Singleton

Dengan CDI (Contexts and Dependency Injection), kita dapat dengan mudah membuat lajang menggunakan anotasi @Singleton . Anotasi ini adalah bagian dari paket javax.inject . Ini menginstruksikan container untuk membuat instance singleton satu kali dan meneruskan referensinya ke objek lain selama injeksi.

Seperti yang bisa kita lihat, implementasi tunggal dengan CDI sangat sederhana:

@Singleton public class CarServiceSingleton { // ... } 

Kelas kami mensimulasikan bengkel mobil. Kami memiliki banyak contoh berbagai Mobil , tetapi semuanya menggunakan toko yang sama untuk servis. Karena itu, Singleton sangat cocok.

Kita bisa memverifikasi itu adalah contoh yang sama dengan tes JUnit sederhana yang menanyakan konteks kelas dua kali. Perhatikan bahwa kami memiliki metode pembantu getBean di sini agar mudah dibaca:

@Test public void givenASingleton_whenGetBeanIsCalledTwice_thenTheSameInstanceIsReturned() { CarServiceSingleton one = getBean(CarServiceSingleton.class); CarServiceSingleton two = getBean(CarServiceSingleton.class); assertTrue(one == two); } 

Karena anotasi @Singleton , penampung akan mengembalikan referensi yang sama di kedua waktu. Jika kita mencoba ini dengan kacang yang dikelola biasa, bagaimanapun, wadah akan memberikan contoh yang berbeda setiap saat.

Dan meskipun ini berfungsi sama untuk javax.inject.Singleton atau javax.ejb.Singleton, ada perbedaan utama di antara keduanya.

4. EJB Singleton

Untuk membuat singleton EJB kita menggunakan anotasi @Singleton dari paket javax.ejb . Dengan cara ini kami membuat Singleton Session Bean.

Kita dapat menguji implementasi ini dengan cara yang sama kita menguji implementasi CDI pada contoh sebelumnya, dan hasilnya akan sama. Lajang EJB, seperti yang diharapkan, menyediakan turunan tunggal kelas.

Namun, EJB Singletons juga menyediakan fungsionalitas tambahan dalam bentuk kontrol konkurensi yang dikelola container.

Saat kami menggunakan jenis implementasi ini, container EJB memastikan bahwa setiap metode publik kelas diakses oleh satu thread pada satu waktu. Jika beberapa utas mencoba mengakses metode yang sama, hanya satu utas yang dapat menggunakannya sementara utas lain menunggu giliran mereka.

Kami dapat memverifikasi perilaku ini dengan tes sederhana. Kami akan memperkenalkan simulasi antrian layanan untuk kelas tunggal kami:

private static int serviceQueue; public int service(Car car) { serviceQueue++; Thread.sleep(100); car.setServiced(true); serviceQueue--; return serviceQueue; } 

serviceQueue diimplementasikan sebagai integer statis biasa yang meningkat saat mobil "memasuki" layanan dan menurun saat "keluar". Jika penguncian yang tepat disediakan oleh penampung, variabel ini harus sama dengan nol sebelum dan sesudah layanan, dan sama dengan satu selama layanan.

Kami dapat memeriksa perilaku itu dengan tes sederhana:

@Test public void whenEjb_thenLockingIsProvided() { for (int i = 0; i < 10; i++) { new Thread(new Runnable() { @Override public void run() { int serviceQueue = carServiceEjbSingleton.service(new Car("Speedster xyz")); assertEquals(0, serviceQueue); } }).start(); } return; } 

Tes ini memulai 10 utas paralel. Setiap utas membuat contoh mobil dan mencoba menyervisnya. Setelah layanan, itu menegaskan bahwa nilai serviceQueue kembali ke nol.

Jika kita, misalnya, menjalankan pengujian serupa pada CDI tunggal, pengujian kita akan gagal.

5. Kesimpulan

Pada artikel ini, kami membahas dua jenis implementasi tunggal yang tersedia di Jakarta EE. Kami melihat kelebihan dan kekurangan mereka dan kami juga mendemonstrasikan bagaimana dan kapan menggunakan masing-masing.

Dan, seperti biasa, kode sumber lengkap tersedia di GitHub.