2010-04-14 27 views
74

Como todos sabemos, tenemos beans como singleton por defecto en el contenedor Spring y si tenemos una aplicación web basada en Spring framework entonces en ese caso necesitamos implementar un patrón de diseño Singleton para contener datos globales en lugar de simplemente crear un frijol durante la primavera.Patrón de diseño singleton vs Singleton beans en contenedor Spring

Por favor tengan paciencia si no puedo explicar lo que realmente quise preguntar.

Respuesta

9

El alcance Singleton en Spring significa que este bean se creará una instancia solo una vez en primavera. En contraste con el alcance del prototipo (nueva instancia cada vez), alcance de la solicitud (una vez por solicitud), alcance de la sesión (una vez por sesión HTTP).

El alcance de Singleton tiene técnicamente que ver con el patrón de diseño singleton. No es necesario que implemente sus beans como singleton para que se incluyan en el ámbito singleton.

+0

Corrígeme si me equivoco, de acuerdo con usted si tengo que implementar cualquier objeto como singleton, por lo que no hay necesidad de implementar el patrón singleton. Crear ese bean usando Spring funcionará.Estoy un poco confundido ahora con mi comprensión relacionada con el patrón de diseño de Singleton y el alcance de Singleton en el marco de Spring. – Peeyush

+1

El resorte no lo obliga a usar el patrón de Singleton. – lexicore

46

Un bean Singleton en Spring y el patrón Singleton son bastante diferentes. El patrón de Singleton dice que se creará una y solo una instancia de una clase en particular por cargador de clases.

El alcance de un singleton Spring se describe como "por contenedor por bean". Es el alcance de la definición de bean a una única instancia de objeto por contenedor Spring IoC. El alcance predeterminado en Spring es Singleton.

Aunque el alcance predeterminado es singleton, puede cambiar el alcance del bean especificando el atributo de alcance del elemento <bean ../>.

<bean id=".." class=".." scope="prototype" /> 
+7

@ user184794: por contenedor por bean, lo que significa que solo hay un cargador de clases en el contenedor de primavera. Si hay dos o más cargadores de clases en el contenedor de primavera, cada cargador de clases tendrá su propia instancia. Significa "por contenedor por cargador de clases por bean". ¡¡la amabilidad de aclarar!! –

+4

creo que significa que un contenedor de Spring usará un solo cargador de clases que posee. lo que haces fuera del mecanismo de Spring no es relevante, es decir, puedes crear tus propios classloaders y crear tantas instancias de una clase como desees, pero si pasas por el contenedor de Spring, no creará más de una instancia – inor

+0

Then no son "muy diferentes" como dices. La única diferencia es el alcance: contenedor de primavera versos classloader –

1

"singleton" en primavera usa la instancia de obtención de fábrica de bean, luego la almacena en caché; qué patrón de diseño singleton es estrictamente, la instancia solo se puede recuperar del método get estático, y el objeto nunca se puede crear una instancia pública.

25

El alcance Singleton en primavera significa una sola instancia en un contexto Spring ...
El contenedor Spring simplemente devuelve la misma instancia una y otra vez para llamadas posteriores para obtener el bean.


Y el resorte no molesta si la clase del bean está codificada como singleton o no, de hecho si la clase está codificada como singleton cuyo constructor como privado, Spring usa BeanUtils.instantiateClass (javadoc here) para establecer el constructor accesible e invocarlo.

Alternativamente, se puede utilizar un atributo de fábrica método en la definición de frijol como éste

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

¿está seguro de que necesita el atributo factory-method? Estoy bastante seguro de que Spring sabe cómo obtener una instancia incluso si el constructor es privado (probablemente intente llamar a getInstance) – inor

+0

Una discusión relacionada sobre cómo Spring invoca el constructor privado [aquí] (http://stackoverflow.com/a/7254617/ 2841265) –

2

granos de Singleton en primavera y clases basadas en el patrón de diseño Singleton son bastante diferentes.

El patrón de Singleton asegura que se creará una y solo una instancia de una clase en particular por cargador de clases, ya que el alcance de un bean único de Spring se describe como 'por contenedor por bean'. El alcance Singleton en Spring significa que este bean se creará una instancia solo una vez para Spring. El contenedor de resorte simplemente devuelve la misma instancia una y otra vez para llamadas posteriores para obtener el bean.

+10

Eres el 'java maverick', ¿verdad? Eso haría que tu declaración, "Encontraste una buena explicación y un ejemplo en ..." un intento deshonesto de ocultar que estás enlazando a tu propio sitio web. Su enlace no parece ser importante para la respuesta, de todos modos. Lo eliminaré para evitar que la respuesta se elimine como spam. Lea las preguntas frecuentes sobre autopromoción antes de publicar más enlaces a su sitio web. También tenga en cuenta que es bastante bueno para usted poner el enlace de su sitio web en su perfil. –

15

Tomemos el ejemplo más simple: usted tiene una aplicación y solo usa el cargador de clases predeterminado. Tienes una clase que, por el motivo que sea, decides que no debe tener más de una instancia en la aplicación. (Piense en un escenario donde varias personas trabajan en piezas de la aplicación).

Si no está utilizando el marco Spring, el patrón Singleton garantiza que no habrá más de una instancia de una clase en su aplicación. Esto se debe a que no puede instanciar instancias de la clase haciendo 'nuevo' porque el constructor es privado. La única forma de obtener una instancia de la clase es llamar a algún método estático de la clase (generalmente llamado 'getInstance') que siempre devuelve la misma instancia.

Decir que está utilizando Spring Framework en su aplicación, solo significa que, además de las formas habituales de obtener una instancia de la clase (métodos nuevos o estáticos que devuelven una instancia de la clase), también puede preguntar Spring para obtener una instancia de esa clase y Spring se asegurará de que siempre que solicite una instancia de esa clase siempre devuelva la misma instancia, incluso si no escribió la clase con el patrón de Singleton. En otras palabras, incluso si la clase tiene un constructor público, si siempre pides a Spring una instancia de esa clase, Spring solo llamará a ese constructor una vez durante la vida de tu aplicación.

Normalmente, si utiliza Spring, solo debe usar Spring para crear instancias, y puede tener un constructor público para la clase. Pero si su constructor no es privado, no está realmente impidiendo que alguien cree nuevas instancias de la clase directamente, evitando Spring.

Si realmente quiere una sola instancia de la clase, incluso si usa Spring en su aplicación y define la clase en Spring como singleton, la única manera de garantizar eso también es implementar la clase utilizando el patrón Singleton. Eso asegura que habrá una sola instancia, ya sea que las personas usen Spring para obtener una instancia o eludir Spring.

1

EX: "por contenedor por grano".

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

primavera se describe como 'por contenedor por bean'. El alcance de Singleton en Spring significa que el mismo objeto en la misma ubicación de memoria se devolverá a la misma id de bean. Si se crean varios beans de diferentes ID de la misma clase, el contenedor devolverá diferentes objetos a diferentes ID. Esto es como un mapeo de valores clave donde key es bean id y value es el bean object en un contenedor de spring. Donde el patrón Singleton asegura que solo se creará una y solo una instancia de una clase en particular por cargador de clases.

1

Encuentro "por contenedor por frijol" difícil de aprehender. Diría "un frijol por ID de frijol". Le damos un ejemplo para entenderlo. Tenemos una muestra de clase de frijol. He definido dos granos de esta clase en la definición de frijol, como:

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

Así, cuando cada vez que intenta conseguir el grano con id "ID1", el contenedor de primavera creará un frijol, caché y volver misma frijol donde alguna vez se refirió con id1. Si trato de obtenerlo con id7, se creará otro bean de la clase Sample, el mismo se almacenará en la memoria caché y se devolverá cada vez que lo mencione con id7.

Esto es poco probable con el patrón Singleton. En el patrón de Singlton, se crea siempre un objeto por cargador de clases. Pero en la primavera se están creando muchos objetos para la misma clase. Sin embargo, en Spring, el ámbito como Singleton devuelve el mismo objeto para la misma ID. Reference