Seperti yang kita semua tahu kita memiliki bean sebagai singleton secara default di Spring container dan jika kita memiliki aplikasi web berdasarkan framework Spring maka dalam hal ini kita benar-benar perlu mengimplementasikan pola desain Singleton untuk menyimpan data global daripada hanya membuat bean melalui spring. .
Mohon bersabarlah jika saya tidak dapat menjelaskan apa yang sebenarnya ingin saya tanyakan.
sumber
Lingkup tunggal di musim semi berarti instance tunggal dalam konteks Spring ..
Container Spring hanya mengembalikan instance yang sama berulang kali untuk panggilan berikutnya untuk mendapatkan bean.
Dan musim semi tidak mengganggu jika kelas kacang dikodekan sebagai tunggal atau tidak, pada kenyataannya jika kelas dikodekan sebagai tunggal yang konstruktornya sebagai pribadi, Spring menggunakan BeanUtils.instantiateClass (javadoc di sini ) untuk mengatur konstruktor agar dapat diakses dan dipanggil Itu.
Alternatifnya, kita dapat menggunakan atribut metode pabrik dalam definisi kacang seperti ini
<bean id="exampleBean" class="example.Singleton" factory-method="getInstance"/>
sumber
Mari kita ambil contoh paling sederhana: Anda memiliki aplikasi dan Anda cukup menggunakan classloader default. Anda memiliki kelas yang, untuk alasan apa pun, Anda memutuskan bahwa kelas itu tidak boleh memiliki lebih dari satu contoh dalam aplikasi. (Pikirkan skenario di mana beberapa orang mengerjakan bagian aplikasi).
Jika Anda tidak menggunakan framework Spring, pola Singleton memastikan bahwa tidak akan ada lebih dari satu instance kelas dalam aplikasi Anda. Itu karena Anda tidak dapat membuat instance kelas dengan melakukan 'baru' karena konstruktornya bersifat pribadi. Satu-satunya cara untuk mendapatkan instance kelas adalah dengan memanggil beberapa metode statis kelas (biasanya disebut 'getInstance') yang selalu mengembalikan instance yang sama.
Mengatakan bahwa Anda menggunakan kerangka kerja Spring dalam aplikasi Anda, berarti selain cara biasa untuk mendapatkan instance kelas (metode baru atau statis yang mengembalikan instance kelas), Anda juga dapat meminta Spring untuk mendapatkan Anda sebuah instance dari kelas itu dan Spring akan memastikan bahwa setiap kali Anda memintanya untuk sebuah instance dari kelas itu, ia akan selalu mengembalikan instance yang sama, bahkan jika Anda tidak menulis kelas tersebut menggunakan pola Singleton. Dengan kata lain, meskipun kelas tersebut memiliki konstruktor publik, jika Anda selalu meminta Spring untuk instance kelas itu, Spring hanya akan memanggil konstruktor itu sekali selama masa pakai aplikasi Anda.
Biasanya jika Anda menggunakan Spring, Anda hanya boleh menggunakan Spring untuk membuat instance, dan Anda dapat memiliki konstruktor publik untuk kelas tersebut. Tetapi jika konstruktor Anda tidak bersifat pribadi, Anda tidak benar-benar mencegah siapa pun membuat instance baru dari kelas secara langsung, dengan melewati Spring.
Jika Anda benar-benar menginginkan satu instance kelas, bahkan jika Anda menggunakan Spring dalam aplikasi Anda dan menentukan kelas di Spring menjadi tunggal, satu-satunya cara untuk memastikan bahwa adalah juga mengimplementasikan kelas menggunakan pola Singleton. Itu memastikan bahwa akan ada satu instance, apakah orang menggunakan Spring untuk mendapatkan instance atau melewati Spring.
sumber
Saya merasa " per kontainer per biji" sulit untuk dipahami . Saya akan mengatakan " satu kacang per id kacang dalam wadah ". Mari kita punya contoh untuk memahaminya. Kami memiliki Sampel kelas kacang. Saya telah mendefinisikan dua kacang dari kelas ini dalam definisi kacang, seperti:
<bean id="id1" class="com.example.Sample" scope="singleton"> <property name="name" value="James Bond 001"/> </bean> <bean id="id7" class="com.example.Sample" scope="singleton"> <property name="name" value="James Bond 007"/> </bean>
Jadi ketika saya mencoba untuk mendapatkan kacang dengan id "id1", wadah pegas akan membuat satu kacang, men-cache-nya dan mengembalikan kacang yang sama dimana pernah direferensikan dengan id1. Jika saya mencoba mendapatkannya dengan id7, kacang lain akan dibuat dari kelas Sampel, kacang yang sama akan di-cache dan dikembalikan setiap kali Anda merujuknya dengan id7.
Ini tidak mungkin terjadi dengan pola Singleton. Dalam pola Singlton, satu objek per pemuat kelas selalu dibuat. Namun di Spring, membuat scope sebagai Singleton tidak membatasi container untuk membuat banyak instance dari class tersebut. Itu hanya membatasi pembuatan objek baru untuk ID yang sama lagi, mengembalikan objek yang dibuat sebelumnya ketika sebuah objek diminta untuk id yang sama . Referensi
sumber
Cakupan tunggal di Spring berarti bahwa kacang ini hanya akan dipakai sekali oleh Spring. Berbeda dengan lingkup prototipe (contoh baru setiap kali), lingkup permintaan (sekali per permintaan), lingkup sesi (sekali per sesi HTTP).
Lingkup singleton secara teknis tidak ada hubungannya dengan pola desain singleton. Anda tidak perlu mengimplementasikan bean Anda sebagai single agar bisa ditempatkan di scope singleton.
sumber
Kacang tunggal di Musim Semi dan kelas berdasarkan pola desain Singleton sangat berbeda.
Pola tunggal memastikan bahwa satu dan hanya satu contoh dari kelas tertentu yang akan pernah dibuat per pemuat kelas dimana ruang lingkup kacang tunggal musim semi dijelaskan sebagai 'per kontainer per kacang'. Cakupan tunggal di Spring berarti bahwa kacang ini hanya akan dipakai sekali oleh Spring. Penampung pegas hanya mengembalikan contoh yang sama berulang kali untuk panggilan berikutnya untuk mendapatkan kacang.
sumber
Ada perbedaan yang sangat mendasar di antara keduanya. Dalam kasus pola desain Singleton, hanya satu contoh kelas yang akan dibuat per classLoader sementara itu tidak terjadi dengan Spring singleton seperti di kemudian satu contoh kacang bersama untuk id yang diberikan per kontainer IoC dibuat.
Misalnya, jika saya memiliki kelas dengan nama "SpringTest" dan file XML saya terlihat seperti ini: -
<bean id="test1" class="com.SpringTest" scope="singleton"> --some properties here </bean> <bean id="test2" class="com.SpringTest" scope="singleton"> --some properties here </bean>
Jadi sekarang di kelas utama jika Anda akan memeriksa referensi dari dua di atas itu akan mengembalikan false sesuai dengan dokumentasi Spring: -
Jadi seperti dalam kasus kami, kelasnya sama tetapi id yang kami berikan berbeda sehingga menghasilkan dua contoh berbeda yang dibuat.
sumber
Semua jawaban, setidaknya sejauh ini, berkonsentrasi pada penjelasan perbedaan antara pola desain dan Spring singleton dan tidak menjawab pertanyaan Anda yang sebenarnya: Haruskah pola desain Singleton digunakan atau Spring singleton bean? apa yang lebih baik?
Sebelum saya menjawab, izinkan saya menyatakan bahwa Anda dapat melakukan keduanya. Anda dapat mengimplementasikan kacang sebagai pola desain Singleton dan menggunakan Spring untuk memasukkannya ke dalam kelas klien sebagai kacang tunggal Spring.
Sekarang, jawaban atas pertanyaannya sederhana: Jangan gunakan pola desain Singleton!
Gunakan kacang tunggal Spring yang diimplementasikan sebagai kelas dengan konstruktor publik.
Mengapa? Karena pola desain Singleton dianggap anti pola. Terutama karena pengujian yang rumit. (Dan jika Anda tidak menggunakan Spring untuk menyuntikkannya, semua kelas yang menggunakan singleton sekarang terikat erat padanya), dan Anda tidak dapat mengganti atau memperpanjangnya. Seseorang dapat google "anti-pola Singleton" untuk mendapatkan info lebih lanjut tentang ini, misalnya anti-pola Singleton
Menggunakan Spring singleton adalah cara yang harus dilakukan (dengan kacang tunggal diimplementasikan BUKAN sebagai pola desain Singleton, melainkan dengan konstruktor publik) sehingga kacang tunggal Spring dapat dengan mudah diuji dan kelas yang menggunakannya tidak digabungkan erat dengannya , tetapi, Spring menyuntikkan singleton (sebagai antarmuka) ke semua kacang yang membutuhkannya, dan kacang tunggal dapat diganti kapan saja dengan implementasi lain tanpa memengaruhi kelas klien yang menggunakannya.
sumber
"singleton" di musim semi menggunakan instance get factory get, lalu menyimpannya dalam cache; dengan pola desain tunggal yang ketat, instance hanya dapat diambil dari metode get statis, dan objek tidak pernah dapat digunakan secara publik.
sumber
EX: "per kontainer per biji".
<bean id="myBean" class="com.spring4hibernate4.TestBean"> <constructor-arg name="i" value="1"></constructor-arg> <property name="name" value="1-name"></property> </bean> <bean id="testBean" class="com.spring4hibernate4.TestBean"> <constructor-arg name="i" value="10"></constructor-arg> <property name="name" value="10-name"></property> </bean> </beans> public class Test { @SuppressWarnings("resource") public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("ws.xml"); TestBean teatBean = (TestBean) ac.getBean("testBean"); TestBean myBean1 = (TestBean) ac.getBean("myBean"); System.out.println("a : " + teatBean.test + " : " + teatBean.getName()); teatBean.setName("a TEST BEAN 1"); System.out.println("uPdate : " + teatBean.test + " : " + teatBean.getName()); System.out.println("a1 : " + myBean1.test + " : " + myBean1.getName()); myBean1.setName(" a1 TEST BEAN 10"); System.out.println("a1 update : " + teatBean.test + " : " + myBean1.getName()); } } public class TestBean { public int test = 0; public String getName() { return name; } public void setName(String name) { this.name = name; } private String name = "default"; public TestBean(int i) { test += i; } }
TUNGGAL JAWA:
public class Singleton { private static Singleton singleton = new Singleton(); private int i = 0; private Singleton() { } public static Singleton returnSingleton() { return singleton; } public void increment() { i++; } public int getInt() { return i; } } public static void main(String[] args) { System.out.println("Test"); Singleton sin1 = Singleton.returnSingleton(); sin1.increment(); System.out.println(sin1.getInt()); Singleton sin2 = Singleton.returnSingleton(); System.out.println("Test"); sin1.increment(); System.out.println(sin1.getInt()); }
sumber
Kacang tunggal musim semi digambarkan sebagai 'per wadah per biji'. Lingkup tunggal di Spring berarti objek yang sama di lokasi memori yang sama akan dikembalikan ke bean id yang sama. Jika seseorang membuat beberapa bean dari id berbeda dari kelas yang sama maka kontainer akan mengembalikan objek yang berbeda ke id yang berbeda. Ini seperti pemetaan nilai kunci di mana kuncinya adalah id kacang dan nilai adalah objek kacang dalam satu wadah pegas. Dimana pola Singleton memastikan bahwa satu dan hanya satu instance dari kelas tertentu yang akan dibuat per classloader.
sumber