wake-up-neo.com

Ist der Frühlings-Standardbereich ein Singleton oder nicht?

Könnten Sie bitte erläutern, warum Spring zwei Objekte für die Konfiguration der unten gezeigten Beans erstellt, da der Standardbereich von Spring standardmäßig Singleton ist?

Die Federkonfiguration ist hier:

<bean id="customer" class="jp.ne.goo.beans.Customer"> 
    <property name="custno" value="100"></property>
    <property name="custName" value="rajasekhar"> </property>
</bean>
<bean id="customer2" class="jp.ne.goo.beans.Customer"> 
    <property name="custno" value="200"></property> 
    <property name="custName" value="siva"></property> 
</bean>
33
Raj

Der Standardbereich von Spring ist Singleton. Es ist nur so, dass Ihre Vorstellung von dem, was es bedeutet, ein Singleton zu sein, nicht der von Spring definierten Definition von Singletons entspricht.

Wenn Sie Spring anweisen, zwei separate Beans mit unterschiedlichen IDs und derselben Klasse zu erstellen, erhalten Sie zwei separate Beans mit jeweils einem Einzelbereich. Alles, was mit einem Singleton-Bereich gemeint ist, heißt, wenn Sie auf etwas mit derselben ID verweisen, erhalten Sie dieselbe Bean-Instanz zurück.

So wird die Spring-Dokumentation definiert den Einzelumfang :

Es wird nur eine gemeinsam genutzte Instanz einer Singleton-Bean verwaltet, und alle Anforderungen für Beans, deren ID oder IDs dieser Bean-Definition entsprechen, führen dazu, dass diese bestimmte Bean-Instanz vom Spring-Container zurückgegeben wird.

Singleton-Bereich bedeutet, dass mit derselben ID die gleiche Bean abgerufen wird. Das Testen, dass keine zwei IDs auf dieselbe Klasse bezogen sind, würde der Verwendung von Karten als Bohnen im Weg stehen und durch das Proxy-Setzen von Objekten mit BeanFactories erschwert werden .. Für Spring zu Polizei würde dies viel Arbeit mit wenig Nutzen bedeuten vertraut den Benutzern darauf, zu wissen, was sie tun.

Um zwei Namen für dieselbe Bean zu definieren, verwenden Sie einen Alias ​​ :

In einer Bean-Definition selbst können Sie mehr als einen Namen für die Bean angeben, indem Sie eine Kombination aus bis zu einem Namen verwenden, der im Attribut id angegeben ist, und einer beliebigen Anzahl anderer Namen im Attribut name. Diese Namen können Aliasnamen für dieselbe Bean sein und sind in bestimmten Situationen hilfreich, z. B. wenn jede Komponente in einer Anwendung auf eine allgemeine Abhängigkeit verweisen darf, indem ein Bean-Name verwendet wird, der für diese Komponente selbst spezifisch ist.

Die Angabe aller Aliase, bei denen die Bean tatsächlich definiert ist, ist jedoch nicht immer ausreichend. Manchmal ist es wünschenswert, einen Alias ​​für eine Bean einzuführen, die an anderer Stelle definiert ist. Dies ist im Allgemeinen in großen Systemen der Fall, bei denen die Konfiguration auf jedes Subsystem aufgeteilt ist, wobei jedes Subsystem seinen eigenen Satz von Objektdefinitionen hat. In XML-basierten Konfigurationsmetadaten können Sie das Element verwenden, um dies zu erreichen.

Wenn Sie also einen Namen in der Bean-Konfiguration hinzufügen:

<bean id="customer" name="customer2" 
    class="jp.ne.goo.beans.Customer">
</bean>

oder erstellen Sie einen Alias ​​für eine anderswo definierte Bean:

<alias name="customer" alias="customer2"/>

dann beziehen sich "customer" und "customer2" auf dieselbe Bean-Instanz.

Der Spring-Standardbereich ist Singleton und es wird ein Objekt für alle Instanzen erstellt, sofern Sie nicht explizit den Bereich als Prototyp angeben. Sie haben keine Federkonfiguration gebucht. Bitte poste es, es wird eine bessere Idee geben.

6
Anupama Rao

Sie deklarieren zwei Beans derselben Klasse. Das ist nicht das Gleiche.

@Component("springTestClass")
public class SpringTestClass{
     private int randomNumber = 0;
     public SpringTestClass(){
       randomNumber = new Random().nextInt(2000);
     }

     public int getRandomNumber(){
       return this.randomNumber;
     }

}

Und versuchen Sie, auf diese Bean an zwei Stellen zuzugreifen, wird die Nummer gleich sein. Sie haben jedoch zwei separate Beans erstellt.

Wenn Sie prüfen möchten, ob dies funktioniert, versuchen Sie Folgendes:

public class Main{
   public static void main(String[] args){
     ApplicationContext ctx = ....;
     SpringTestClass testObject1 = (SpringTestClass)ctx.getBean("springTestClass");
     SpringTestClass testObject2 = (SpringTestClass)ctx.getBean("springTestClass");

    System.out.println(testObject1.getRandomNumber() == testObject2.getRandomNumber());
   }
}

Dieser Code sollte true zurückgeben, wenn es sich um dieselbe Instanz handelt In SpringTestClass können Sie jedoch die Annotation @Scope ("prototype") hinzufügen. .__ Die Ausgabe ist falsch

2
Berrigan

Wie andere bereits erwähnt haben, sollten zwei Beans aus dem von Ihnen geposteten Code erstellt werden. Singletons werden wie folgt definiert (aus der Spring-Dokumentation: Singleton Scope )

Es wird nur eine gemeinsam genutzte Instanz einer Singleton-Bean verwaltet, und alle Anforderungen für Beans, deren ID oder IDs dieser Bean-Definition entsprechen, führen dazu, dass diese bestimmte Bean-Instanz vom Spring-Container zurückgegeben wird.

Um dies klarer zu machen, wird die Bedeutung von "Shared Instance" im folgenden Abschnitt erläutert:

alle nachfolgenden Anforderungen und Referenzen für diese benannte Bean geben das zwischengespeicherte Objekt zurück

Wenn eine Singleton-Bean erstellt wird, wird nur ein Bean-Objekt instanziiert und zwischengespeichert. Dies bezieht sich nur auf die Bean, nicht auf die Klasse, für die die Bean eine Instanz ist. Zum Beispiel,

<bean id="myBean" class="myPackage.myClass" />

<bean id="myOtherBean1 class="myPackage.myOtherClass1">
    <property name="beanReference1" ref="myBean" />
</bean>
<bean id="myOtherBean2 class="myPackage.myOtherClass2">
    <property name="beanReference2" ref="myBean" />
</bean>

In dieser konfigurierten Konfiguration haben "myOtherBean1" und "myOtherBean2" Verweise auf dieselbe Bean "myBean", also auf dieselbe Instanz "myPackage.myClass". Wenn Sie den Code geändert haben, um eine zweite Bean "myPackage.myClass" hinzuzufügen, würde sich diese von "myBean" unterscheiden.

Um dies vollständig zu verstehen, beziehen Sie sich auch auf den anderen Spring-Bereich: den Prototyp. Aus der Spring-Dokumentation für Prototyp Scope :

Der Nicht-Einzel-Prototyp-Geltungsbereich der Bean-Bereitstellung führt zur Erstellung einer neuen Bean-Instanz jedes Mal, wenn eine Anforderung für diese bestimmte Bean gestellt wird.

Das heißt, wenn wir dasselbe Spring-XML wie oben verwenden würden, würden "myOtherBean1" und "myOtherBean2" jeweils ihre eigenen unterschiedlichen Kopien von "myBean" erhalten, was immer noch eine Instanz von "myPackage.myClass" ist.

2
ryoung10

Sie verwirren zwei verschiedene Konzepte.

Das Word-Singleton im Frühjahr wird für einen Bean-Bereich verwendet. Das bedeutet, dass die Bean nur einmal für die gesamte Anwendung erstellt wird. 

Die gewöhnliche Bedeutung von Singleton bezieht sich auf das GOF-Muster. Es ist ein objektorientiertes Muster, das garantiert, dass nur eine Instanz einer Klasse vorhanden ist (zumindest im Geltungsbereich des classLoader). 

1
Gab

Das folgende Beispiel zeigt eine annotierte @Bean-Methode, die aufgerufen wird zweimal:

@Configuration
public class AppConfig {

    @Bean
    public ClientService clientService1() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientService clientService2() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientDao clientDao() {
        return new ClientDaoImpl();
    }

}

clientDao () wurde einmal in clientService1 () und einmal in .__ aufgerufen. clientService2 (). Da diese Methode eine neue Instanz von .__ erstellt. ClientDaoImpl und gibt es zurück. Normalerweise erwarten Sie 2 Instanzen (eine für jeden Dienst). Das wäre definitiv problematisch: Im Frühling haben instantiierte Beans einen Einzelbereichs von Standard. Hier kommt die Magie ins Spiel: Alle @Configuration-Klassen werden beim Start mit CGLIB untergeordnet. In der Unterklasse das Kind Diese Methode prüft den Container zuerst auf zwischengespeicherte (bereichsabhängige) Beans vor Es ruft die übergeordnete Methode auf und erstellt eine neue Instanz. Beachten Sie das ab Im Frühling 3.2 ist es nicht mehr erforderlich, CGLIB zu Ihrem Klassenpfad hinzuzufügen weil CGLIB-Klassen unter .__ umgepackt wurden. org.springframework.cglib und direkt im Federkern enthalten KRUG.

0

Spring Singleton Bean Funktioniert nicht wie Java Singleton.

Wenn wir schreiben

ApplicationContext ctx = new ClassPathXmlApplicationContext("MyConfig.xml");
        Customer obj1= (Customer) ctx.getBean("customer");
        Customer obj2 = (Customer) ctx.getBean("customer2");
        System.out.println(obj1 == obj2);
        System.out.println(obj1+ "::" + obj2);

Wenn wir die Ausgabe sehen, werden 2 verschiedene Instanzen zurückgegeben. Laut Spring Docs Bean ist Singleton, es wird nur eine gemeinsam genutzte Instanz verwaltet, und alle Request-Beans mit einer ID oder ID, die mit dieser Bean-Definition übereinstimmt. Hier stehen 2 verschiedene IDs zur Verfügung.

Federbehälter als verwaltendes Schlüsselwertpaar, Schlüssel als ID/Name und Wert ist Bean.

0
gopal jha

In SPring verweist Singleton auf eine Bean pro Spring-Container, wobei Singleton wie in Java) auf ein Objekt pro Klassenladeprogramm verweist.

Spring Singleton ist also nicht dasselbe wie Java Singleton. Verwechseln Sie die beiden nicht.

0
Pritam