web-dev-qa-db-fra.com

Motif de conception Singleton vs Haricots Singleton dans un récipient Spring

Comme nous le savons tous, nous avons des beans singleton par défaut dans le conteneur Spring. Si nous avons une application Web basée sur le framework Spring, nous devons dans ce cas implémenter un modèle de conception Singleton pour conserver les données globales plutôt que de simplement créer un bean jusqu'au printemps. .

Veuillez supporter si je ne suis pas capable d'expliquer ce que je voulais réellement demander.

86
Peeyush

Un singleton haricot au printemps et le motif singleton sont très différents. Le modèle Singleton indique qu'une et une seule instance d'une classe particulière sera jamais créée par chargeur de classe.

La portée d'un singleton Spring est décrite comme "par conteneur par haricot". Il s'agit de l'étendue de la définition du bean pour une instance d'objet unique par conteneur Spring IoC. L'étendue par défaut de Spring est Singleton.

Même si la portée par défaut est singleton, vous pouvez modifier la portée du bean en spécifiant l'attribut scope de <bean ../> élément.

<bean id=".." class=".." scope="prototype" />
54
user184794

Singleton scope in spring signifie une instance unique dans un contexte Spring.
Le conteneur Spring renvoie simplement la même instance encore et encore pour les appels suivants afin d'obtenir le bean.


Et le printemps ne dérange pas si la classe du haricot est codée singleton ou non, en fait si la classe est codée comme singleton dont le constructeur est privé, Spring utilise BeanUtils.instantiateClass (javadoc ici ) pour rendre le constructeur accessible et l'invoquer.

Alternativement, nous pouvons utiliser un attribut factory-method dans la définition du bean comme ceci

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

Prenons l'exemple le plus simple: vous avez une application et vous utilisez simplement le chargeur de classes par défaut. Vous avez une classe pour laquelle, pour une raison quelconque, vous décidez qu'elle ne devrait pas avoir plus d'une instance dans l'application. (Pensez à un scénario où plusieurs personnes travaillent sur des éléments de l'application).

Si vous n'utilisez pas le framework Spring, le modèle Singleton garantit qu'il n'y aura pas plus d'une instance d'une classe dans votre application. En effet, vous ne pouvez pas instancier des instances de la classe en faisant "new" car le constructeur est privé. Le seul moyen d'obtenir une instance de la classe consiste à appeler une méthode statique de la classe (généralement appelée 'getInstance') qui renvoie toujours la même instance.

Dire que vous utilisez le framework Spring dans votre application signifie simplement qu'en plus des moyens habituels d'obtenir une instance de la classe (méthodes nouvelles ou statiques renvoyant une instance de la classe), vous pouvez également demander à Spring de vous obtenir une instance de cette classe et Spring s'assurent que chaque fois que vous lui demandez une instance de cette classe, elle retournera toujours la même instance, même si vous n'avez pas écrit la classe à l'aide du modèle Singleton. En d'autres termes, même si la classe a un constructeur public, si vous demandez toujours à Spring une instance de cette classe, Spring n'appellera ce constructeur qu'une seule fois pendant la vie de votre application.

Normalement, si vous utilisez Spring, vous ne devez utiliser Spring que pour créer des instances, et vous pouvez avoir un constructeur public pour la classe. Mais si votre constructeur n'est pas privé, vous n'empêchez vraiment personne de créer directement de nouvelles instances de la classe, en contournant Spring.

Si vous voulez vraiment une instance unique de la classe, même si vous utilisez Spring dans votre application et définissez la classe Spring comme un singleton, le seul moyen de vous assurer que cette classe est également implémentée à l'aide du modèle Singleton. Cela garantit qu'il n'y aura qu'une seule instance, que les utilisateurs utilisent Spring pour obtenir une instance ou l'ignorent.

19
inor

La portée de Singleton au printemps signifie que ce haricot ne sera instancié qu’une fois d’ici au printemps. Contrairement à la portée du prototype (nouvelle instance à chaque fois), la portée de la demande (une fois par demande), la portée de la session (une fois par session HTTP).

Singleton scope a techniquement remarqué le modèle de conception singleton. Vous n'avez pas à implémenter vos haricots en tant que singlet pour que ceux-ci soient placés dans le champ singleton.

10
lexicore

Je trouve "par conteneur par haricot" difficile à appréhender. Je dirais "un haricot par haricot" .Perminons un exemple pour le comprendre. Nous avons un échantillon de classe de haricot. J'ai défini deux haricots de cette classe dans la définition de haricot, comme:

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

Ainsi, chaque fois que j'essaie d'obtenir le haricot avec l'id "id1", le conteneur de printemps créera un haricot, le mettra en cache et renverra le même haricot où référé avec id1. Si j'essaie de l'obtenir avec id7, un autre bean sera créé à partir de la classe Sample, la même chose sera mise en cache et renvoyée à chaque fois que vous avez fait référence à cela avec id7.

Ceci est peu probable avec le motif Singleton. Dans le modèle Singlton, un objet par chargeur de classe est toujours créé. Mais au printemps, de nombreux objets sont créés pour la même classe. Cependant, au printemps, la portée de Singleton renvoyait le même objet pour le même identifiant. référence

4
Dexter

Les haricots Singleton au printemps et les cours basés sur le modèle de conception Singleton sont très différents.

Le modèle Singleton garantit qu’une et une seule instance d’une classe particulière sera jamais créée par chargeur de classe, la portée d’un bean Spring Singleton étant alors définie comme "par conteneur par bean". La portée de Singleton au printemps signifie que ce haricot ne sera instancié qu’une fois d’ici au printemps. Le conteneur Spring renvoie simplement la même instance encore et encore pour les appels suivants afin d'obtenir le bean.

2
JavaMave

Il y a une différence fondamentale entre les deux. Dans le cas d'un modèle de conception Singleton, une seule instance d'une classe sera créée par classLoader, alors que ce n'est pas le cas avec Spring singleton, car dans l'instance la plus récente, un bean partagé pour l'ID donné par conteneur IoC est créé.

Par exemple, si j'ai une classe nommée "SpringTest" et que mon fichier XML ressemble à ceci:

<bean id="test1" class="com.SpringTest" scope="singleton">
        --some properties here
</bean>    
<bean id="test2" class="com.SpringTest" scope="singleton">
        --some properties here   
</bean>

Alors maintenant, dans la classe principale, si vous vérifiez la référence des deux précédents, elle retournera la valeur false conformément à la documentation Spring: -

Lorsqu'un bean est un singleton, une seule instance partagée du bean est gérée et toutes les demandes de beans avec un identifiant ou des identifiants correspondant à cette définition de bean entraînent le renvoi d'une instance de bean spécifique par le conteneur Spring.

Donc, comme dans notre cas, les classes sont les mêmes mais les identifiants que nous avons fournis sont différents, ce qui entraîne la création de deux instances différentes.

2
hhhakki

"singleton" au printemps utilise l’instance d’obtention d’usine de haricots, puis la cache; quel modèle de conception singleton est strictement, l'instance ne peut être extraite que de la méthode get statique et l'objet ne peut jamais être instancié publiquement.

1
lwpro2

EX: "par conteneur par haricot".

        <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());
    }
1
Hariprasad

Le haricot singleton de printemps est décrit comme "par contenant par haricot". La portée singleton dans Spring signifie que le même objet situé au même emplacement mémoire sera retourné au même identifiant de bean. Si l'on crée plusieurs beans avec différents identifiants de la même classe, le conteneur renverra des objets différents avec des identifiants différents. Cela ressemble à un mappage de valeur de clé où clé est l'ID de bean et la valeur est l'objet de bean dans un conteneur Spring. Where, en tant que Singleton, garantit qu’une et une seule instance d’une classe donnée sera jamais créée par chargeur de classe.

1
Sibaprasad Sahoo