2010-04-14 9 views
74

Wie wir alle wissen, wir haben Bohnen als Singleton standardmäßig in Spring-Container und wenn wir eine Web-Anwendung basierend auf Spring-Framework dann müssen wir wirklich Singleton Design-Muster implementieren um globale Daten zu speichern, anstatt nur eine Bohne durch den Frühling zu schaffen.Singleton Entwurfsmuster vs Singleton Bohnen im Frühjahr Container

Bitte tragen Sie mit mir, wenn ich nicht in der Lage bin zu erklären, was ich eigentlich fragen wollte.

Antwort

9

Singleton-Bereich in Spring bedeutet, dass diese Bean nur einmal von Spring instanziiert wird. Im Gegensatz zum Prototypbereich (jedes Mal neue Instanz), Anforderungsbereich (einmal pro Anforderung), Sitzungsumfang (einmal pro HTTP-Sitzung).

Singleton Umfang hat technisch mit dem Singleton-Design-Muster zu tun. Sie müssen Ihre Beans nicht als Singletons implementieren, damit sie in den Singleton-Bereich gesetzt werden können.

+0

Korrigieren Sie mich, wenn ich falsch liege, also nach Ihnen, wenn ich jedes Objekt als Singleton implementieren muss, so gibt es keine Notwendigkeit, Singleton-Muster zu implementieren. Das Erstellen dieser Bean mithilfe von Spring funktioniert.Ich bin ein wenig verwirrt jetzt mit meinem Verständnis in Bezug auf Singleton Design-Muster und Singleton Umfang in Spring-Framework. – Peeyush

+1

Spring zwingt Sie nicht, das Singleton-Muster zu verwenden. – lexicore

46

Eine Singleton-Bohne im Frühling und das Singleton-Muster sind ziemlich unterschiedlich. Das Singleton-Muster besagt, dass immer nur eine Instanz einer bestimmten Klasse pro Klassenlader erstellt wird.

Der Umfang eines Spring Singleton wird als "pro Container pro Bean" beschrieben. Es ist der Bereich der Bean-Definition für eine einzelne Objektinstanz pro Spring-IoC-Container. Der Standardbereich in Spring ist Singleton.

Obwohl der Standardbereich Singleton ist, können Sie den Bereich von Bean ändern, indem Sie das Attribut scope des Elements <bean ../> angeben.

+7

@ user184794: pro Container pro Bean, was bedeutet, dass es nur einen Klassenlader im Spring Container gibt. Wenn es zwei oder mehr Classloader im Spring Container gibt, dann hat jeder Classloader eine eigene Instanz. Bedeutet es "pro Container pro Classloader pro Bean". bitte klären !! –

+4

Ich denke, es bedeutet, dass ein Spring-Container einen einzelnen Klassenlader verwendet, den es besitzt. Was Sie außerhalb des Mechanismus von Spring tun, ist nicht relevant, dh Sie können Ihre eigenen Klassenlader erstellen und so viele Instanzen einer Klasse erstellen, wie Sie möchten. Wenn Sie jedoch den Spring-Container durchlaufen, wird nicht mehr als eine Instanz – inor

+0

Dann erstellt Sie sind nicht "ganz anders", wie Sie sagen. Der einzige Unterschied ist der Umfang - Spring container verse classloader –

1

"Singleton" im Frühjahr ist Bean Bean-Instanz verwenden, dann Cache; welches Singleton-Entwurfsmuster strikt ist, kann die Instanz nur von der statischen Get-Methode abgerufen werden, und das Objekt kann niemals öffentlich instanziiert werden.

25

Singleton-Bereich im Frühjahr bedeutet Einzelinstanz in einem Spring-Kontext.
Spring Container gibt die gleiche Instanz immer wieder für nachfolgende Aufrufe, um die Bean zu erhalten.


Und der Frühling nicht stört, wenn die Klasse der Bohne als Singleton codiert ist oder nicht, in der Tat, wenn die Klasse als Singleton, dessen Konstruktor als privat codiert, Frühling verwendet BeanUtils.instantiateClass (javadoc here) den Konstruktor gesetzt zugänglich machen und aufrufen.

Alternativ können wir eine Fabrik-Methode Attribut in Bohne Definition wie folgt

<bean id="exampleBean" class="example.Singleton" factory-method="getInstance"/> 
+1

Sind Sie sicher, dass Sie das Attribut factory-method benötigen? Ich bin mir ziemlich sicher, dass Spring weiß, wie man eine Instanz erhält, selbst wenn der Konstruktor privat ist (versucht wahrscheinlich, getInstance aufzurufen) – inor

+0

Eine verwandte Diskussion darüber, wie Spring privaten Konstruktor [hier] aufruft (http://stackoverflow.com/a/7254617/ 2841265) –

2

Singleton Bohnen im Frühjahr und Klassen basierend auf Singleton-Entwurfsmuster verwenden, sind recht unterschiedlich.

Das Singleton-Muster stellt sicher, dass immer nur eine Instanz einer bestimmten Klasse pro Klassenlader erstellt wird. Der Bereich einer Spring-Singleton-Bean wird als "pro Container pro Bean" beschrieben. Singleton-Bereich in Spring bedeutet, dass diese Bean nur einmal von Spring instanziiert wird. Der Spring-Container gibt die gleiche Instanz immer wieder für nachfolgende Aufrufe zurück, um die Bean zu erhalten.

+10

Sie sind der 'java maverick', richtig? Das würde Ihre Aussage "Eine gute Erklärung und ein gutes Beispiel gefunden" als unehrlichen Versuch darstellen, zu verbergen, dass Sie auf Ihre eigene Website verlinken. Ihr Link scheint für die Antwort sowieso nicht wichtig zu sein. Ich entferne es, um zu vermeiden, dass die Antwort als Spam gelöscht wird. Bitte lesen Sie die FAQ zu Self-Promotion, bevor Sie weitere Links zu Ihrer Website veröffentlichen. Beachten Sie auch, dass es ziemlich gut ist, wenn Sie den Link Ihrer Website in Ihr Profil einfügen. –

15

Nehmen wir das einfachste Beispiel: Sie haben eine Anwendung und Sie verwenden nur den Standard-Classloader. Sie haben eine Klasse, die aus irgendeinem Grund entscheidet, dass nicht mehr als eine Instanz in der Anwendung enthalten sein soll. (Denken Sie an ein Szenario, in dem mehrere Personen an Teilen der Anwendung arbeiten).

Wenn Sie das Spring-Framework nicht verwenden, stellt das Singleton-Muster sicher, dass in Ihrer Anwendung nicht mehr als eine Instanz einer Klasse vorhanden ist. Das liegt daran, dass Sie Instanzen der Klasse nicht instanziieren können, indem Sie "neu" ausführen, da der Konstruktor privat ist. Die einzige Möglichkeit, eine Instanz der Klasse zu erhalten, besteht darin, eine statische Methode der Klasse aufzurufen (normalerweise 'getInstance' genannt), die immer dieselbe Instanz zurückgibt.

Die Angabe, dass Sie das Spring-Framework in Ihrer Anwendung verwenden, bedeutet nur, dass Sie 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 fragen können Spring, um eine Instanz dieser Klasse zu erhalten, und Spring stellt sicher, dass immer, wenn Sie nach einer Instanz dieser Klasse fragen, immer dieselbe Instanz zurückgibt, auch wenn Sie die Klasse nicht mit dem Singleton-Muster geschrieben haben. Mit anderen Worten, selbst wenn die Klasse einen öffentlichen Konstruktor hat, wird Spring diesen Spring-Konstruktor nur einmal während der Laufzeit Ihrer Anwendung aufrufen, wenn Sie Spring immer nach einer Instanz dieser Klasse fragen.

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. Aber wenn Ihr Konstruktor nicht privat ist, verhindern Sie nicht wirklich, dass jemand direkt neue Instanzen der Klasse erzeugt, indem er Spring umgeht.

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 auch die Klasse mithilfe des Singleton-Musters implementiert wird. Dies stellt sicher, dass es eine einzige Instanz gibt, ob Benutzer Spring verwenden, um eine Instanz abzurufen oder Spring zu umgehen.

1

EX: "pro Behälter pro Bohne".

 <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; 
    } 
} 

JAVA SINGLETON:

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()); 
    } 
+0

\t \t \t \t \t \t \t \t \t \t \t Hariprasad

0

Frühling Singleton Bohne wird als 'pro Behälter pro Bohne' beschrieben. Der Singleton-Bereich in Spring bedeutet, dass dasselbe Objekt am selben Speicherort an dieselbe Bean-ID zurückgegeben wird. Wenn man mehrere Beans mit verschiedenen IDs der gleichen Klasse erstellt, werden durch den Container unterschiedliche Objekte an unterschiedliche IDs zurückgegeben. Dies ist wie ein Schlüsselwert-Mapping, bei dem der Schlüssel die Bean-ID ist und der Wert das Bean-Objekt in einem Spring-Container ist. Wo als Singleton-Muster sichergestellt wird, dass immer nur eine Instanz einer bestimmten Klasse pro Klassenlader erstellt wird.

1

Ich finde "per Container per Bean" schwierig zu verstehen. Ich würde sagen "Eine Bohne pro Bohne id". Wir haben ein Beispiel, um es zu verstehen. Wir haben eine Bean-Klasse Sample. Ich habe zwei Bohnen aus dieser Klasse in der Bean-Definition definiert, wie:

<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> 

Also, wann immer ich versuche, die Bohne mit der ID „id1“ zu bekommen, werden die Federbehälter eine Bohne, Cache es schaffen und die Rück gleiche Bohne wo immer mit id1 referiert wurde. Wenn ich versuche, es mit ID7 zu bekommen, wird eine andere Bean aus der Sample-Klasse erzeugt, die jedes Mal zwischengespeichert und zurückgegeben wird, wenn Sie diese mit id7 referenzieren.

Dies ist unwahrscheinlich mit Singleton-Muster. Im Singlton-Muster wird immer ein Objekt pro Klassenlader erstellt. Aber im Frühling werden viele Objekte für die gleiche Klasse geschaffen. Im Frühling macht der Geltungsbereich jedoch Singleton, der dasselbe Objekt für dieselbe ID zurückgibt. Reference

Verwandte Themen