Wie wir alle wissen, haben wir Beans standardmäßig als Singleton im Spring-Container. Wenn wir eine Webanwendung haben, die auf dem Spring-Framework basiert, müssen wir in diesem Fall wirklich das Singleton-Entwurfsmuster implementieren, um globale Daten zu speichern, anstatt nur eine Bean durch Spring zu erstellen .
Bitte nehmen Sie Kontakt mit mir auf, wenn ich nicht erklären kann, was ich eigentlich fragen wollte.
quelle
Singleton-Bereich im Frühjahr bedeutet einzelne Instanz in einem Spring-Kontext. Der
Spring-Container gibt lediglich immer wieder dieselbe Instanz für nachfolgende Aufrufe zurück, um die Bean abzurufen.
Und Spring stört es nicht, ob die Klasse der Bean als Singleton codiert ist oder nicht. Wenn die Klasse als Singleton codiert ist, dessen Konstruktor als privat bezeichnet wird, verwendet Spring BeanUtils.instantiateClass ( hier javadoc ), um den Konstruktor auf access und invoke zu setzen es.
Alternativ können wir in dieser Bean-Definition ein Factory-Methodenattribut verwenden
quelle
Nehmen wir das einfachste Beispiel: Sie haben eine Anwendung und verwenden nur den Standardklassenlader. Sie haben eine Klasse, die aus irgendeinem Grund entscheidet, dass sie nicht mehr als eine Instanz in der Anwendung enthalten soll. (Stellen Sie sich ein Szenario vor, in dem mehrere Personen an Teilen der Anwendung arbeiten.)
Wenn Sie das Spring-Framework nicht verwenden, stellt das Singleton-Muster sicher, dass Ihre Anwendung nicht mehr als eine Instanz einer Klasse enthält. Dies liegt daran, dass Sie Instanzen der Klasse nicht instanziieren können, indem Sie 'new' ausführen, da der Konstruktor privat ist. Die einzige Möglichkeit, eine Instanz der Klasse abzurufen, besteht darin, eine statische Methode der Klasse (normalerweise 'getInstance' genannt) aufzurufen, die immer dieselbe Instanz zurückgibt.
Wenn Sie sagen, dass Sie das Spring-Framework in Ihrer Anwendung verwenden, bedeutet dies nur, dass Sie Spring zusätzlich zu den regulären Methoden zum Abrufen einer Instanz der Klasse (neue oder statische Methoden, die eine Instanz der Klasse zurückgeben) auch bitten können, Sie zu erhalten Eine Instanz dieser Klasse und Spring stellen sicher, dass immer dann, wenn Sie nach einer Instanz dieser Klasse fragen, dieselbe Instanz zurückgegeben wird, auch wenn Sie die Klasse nicht mit dem Singleton-Muster geschrieben haben. Mit anderen Worten, selbst wenn die Klasse einen öffentlichen Konstruktor hat und Spring immer nach einer Instanz dieser Klasse fragt, ruft Spring diesen Konstruktor während der Lebensdauer Ihrer Anwendung nur einmal auf.
Wenn Sie Spring verwenden, sollten Sie Spring normalerweise nur zum Erstellen von Instanzen verwenden, und Sie können einen öffentlichen Konstruktor für die Klasse haben. Wenn Ihr Konstruktor jedoch nicht privat ist, verhindern Sie nicht wirklich, dass jemand direkt neue Instanzen der Klasse erstellt, indem Sie Spring umgehen.
Wenn Sie wirklich eine einzelne Instanz der Klasse möchten, auch wenn Sie Spring in Ihrer Anwendung verwenden und die Klasse in Spring als Singleton definieren, können Sie nur sicherstellen, dass die Klasse auch mithilfe des Singleton-Musters implementiert wird. Dies stellt sicher, dass es eine einzelne Instanz gibt, unabhängig davon, ob Benutzer Spring verwenden, um eine Instanz abzurufen, oder Spring umgehen.
quelle
Singleton-Bereich im Frühjahr bedeutet, dass diese Bean von Spring nur einmal instanziiert wird. Im Gegensatz zum Prototypbereich (jedes Mal neue Instanz), Anforderungsbereich (einmal pro Anforderung), Sitzungsbereich (einmal pro HTTP-Sitzung).
Der Singleton-Bereich hat technisch nichts mit dem Singleton-Entwurfsmuster zu tun. Sie müssen Ihre Beans nicht als Singletons implementieren, damit sie in den Singleton-Bereich eingefügt werden.
quelle
Ich finde " pro Behälter pro Bohne" schwer zu verstehen . Ich würde sagen " eine Bean pro Bean-ID in einem Container ". Lassen Sie uns ein Beispiel haben, um es zu verstehen. Wir haben eine Bohnenklassenprobe. Ich habe zwei Bohnen aus dieser Klasse in der Bohnendefinition definiert, wie:
Wenn ich also versuche, die Bean mit der ID "id1" abzurufen, erstellt der Spring-Container eine Bean, speichert sie im Cache und gibt dieselbe Bean zurück, auf die jemals mit id1 verwiesen wurde. Wenn ich versuche, es mit id7 abzurufen, wird eine weitere Bean aus der Sample-Klasse erstellt. Diese wird jedes Mal zwischengespeichert und zurückgegeben, wenn Sie dies mit id7 referenziert haben.
Dies ist bei Singleton-Mustern unwahrscheinlich. Im Singlton-Muster wird immer ein Objekt pro Klassenlader erstellt. Wenn Sie jedoch im Frühjahr den Bereich als Singleton festlegen, kann der Container nicht viele Instanzen aus dieser Klasse erstellen. Es schränkt lediglich die Erstellung neuer Objekte für dieselbe ID erneut ein und gibt das zuvor erstellte Objekt zurück, wenn ein Objekt für dieselbe ID angefordert wird . Referenz
quelle
Singleton-Bohnen im Frühjahr und Klassen, die auf dem Singleton-Entwurfsmuster basieren, sind sehr unterschiedlich.
Das Singleton-Muster stellt sicher, dass pro Klassenlader immer nur eine Instanz einer bestimmten Klasse erstellt wird, wobei der Umfang einer Spring-Singleton-Bean als "pro Container pro Bean" beschrieben wird. Singleton-Bereich im Frühjahr bedeutet, dass diese Bean von Spring nur einmal instanziiert wird. Spring Container gibt lediglich immer wieder dieselbe Instanz für nachfolgende Aufrufe zurück, um die Bean abzurufen.
quelle
Es gibt einen sehr grundlegenden Unterschied zwischen den beiden. Im Fall eines Singleton-Entwurfsmusters wird nur eine Instanz einer Klasse pro classLoader erstellt, während dies bei Spring Singleton nicht der Fall ist, da in der späteren Version eine gemeinsam genutzte Bean-Instanz für die angegebene ID pro IoC-Container erstellt wird.
Wenn ich zum Beispiel eine Klasse mit dem Namen "SpringTest" habe und meine XML-Datei ungefähr so aussieht: -
Wenn Sie also in der Hauptklasse die Referenz der beiden oben genannten überprüfen, wird gemäß der Spring-Dokumentation false zurückgegeben: -
Wie in unserem Fall sind die Klassen gleich, aber die von uns angegebenen IDs sind unterschiedlich, sodass zwei verschiedene Instanzen erstellt werden.
quelle
"singleton" verwendet im Frühjahr die Bean Factory-Get-Instanz und speichert sie dann im Cache. Welches Singleton-Entwurfsmuster streng genommen ist, die Instanz kann nur von der statischen get-Methode abgerufen werden, und das Objekt kann niemals öffentlich instanziiert werden.
quelle
EX: "pro Behälter pro Bohne".
JAVA SINGLETON:
quelle
Spring Singleton Bean wird als "pro Container pro Bohne" beschrieben. Singleton-Bereich in Spring bedeutet, dass dasselbe Objekt am selben Speicherort an dieselbe Bean-ID zurückgegeben wird. Wenn mehrere Beans mit unterschiedlichen IDs derselben Klasse erstellt werden, gibt der Container unterschiedliche Objekte an unterschiedliche IDs zurück. Dies ist wie eine Schlüsselwertzuordnung, bei der der Schlüssel die Bean-ID und der Wert das Bean-Objekt in einem Federcontainer ist. Wobei als Singleton-Muster sichergestellt wird, dass pro Klassenlader immer nur eine Instanz einer bestimmten Klasse erstellt wird.
quelle
Zumindest bis jetzt konzentrieren sich alle Antworten darauf, den Unterschied zwischen dem Entwurfsmuster und dem Spring-Singleton zu erklären, und gehen nicht auf Ihre eigentliche Frage ein: Sollte ein Singleton-Entwurfsmuster oder eine Spring-Singleton-Bean verwendet werden? was ist besser?
Bevor ich antworte, möchte ich nur sagen, dass Sie beides können. Sie können die Bean als Singleton-Entwurfsmuster implementieren und Spring verwenden, um sie als Spring-Singleton-Bean in die Clientklassen einzufügen.
Die Antwort auf die Frage ist jetzt einfach: Verwenden Sie nicht das Singleton-Entwurfsmuster!
Verwenden Sie die Singleton-Bean von Spring, die als Klasse mit öffentlichem Konstruktor implementiert ist.
Warum? Weil das Singleton-Entwurfsmuster als Anti-Muster betrachtet wird. Meistens, weil es das Testen erschwert. (Und wenn Sie Spring nicht zum Injizieren verwenden, sind jetzt alle Klassen, die den Singleton verwenden, eng daran gebunden.) Sie können ihn nicht ersetzen oder erweitern. Man kann "Singleton Anti-Pattern" googeln, um weitere Informationen zu diesem Thema zu erhalten, z. B. Singleton Anti-Pattern
Die Verwendung von Spring-Singleton ist der richtige Weg (mit einer Singleton-Bean, die NICHT als Singleton-Entwurfsmuster implementiert ist, sondern mit einem öffentlichen Konstruktor), damit die Spring-Singleton-Bean leicht getestet werden kann und Klassen, die sie verwenden, nicht eng daran gekoppelt sind Stattdessen injiziert Spring den Singleton (als Schnittstelle) in alle Beans, die ihn benötigen, und der Singleton-Bean kann jederzeit durch eine andere Implementierung ersetzt werden, ohne dass dies Auswirkungen auf die Clientklassen hat, die ihn verwenden.
quelle