what the mvc for business annotation java spring dependency-injection singleton spring-ioc

java - the - ¿El alcance predeterminado de primavera es singleton o no?



spring singleton annotation (8)

El siguiente ejemplo muestra un método anotado @Bean que se llama dos veces:

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

Se ha llamado a clientDao () una vez en clientService1 () y una vez en clientService2 (). Dado que este método crea una nueva instancia de ClientDaoImpl y la devuelve, normalmente esperaría tener 2 instancias (una para cada servicio). Eso definitivamente sería problemático: en Spring, los beans instanciados tienen un alcance singleton por defecto. Aquí es donde entra la magia: todas las clases de @Configuration se subclasifican en el momento de inicio con CGLIB. En la subclase, el método secundario comprueba primero el contenedor en busca de beans almacenados en caché (con ámbito) antes de llamar al método principal y crea una nueva instancia. Tenga en cuenta que a partir de Spring 3.2, ya no es necesario agregar CGLIB a su classpath porque las clases CGLIB se han reempaquetado en org.springframework.cglib y se han incluido directamente en el JAR de spring-core.

¿Podría explicar por qué Spring está creando dos objetos para la configuración de beans que se muestran a continuación, ya que por defecto el alcance predeterminado de Spring es singleton?

La configuración de Spring está aquí:

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


Como otros han mencionado, se deben crear dos beans a partir del código que publicó. Los Singletons se definen de la siguiente manera (de la documentación de Spring: Singleton Scope )

Solo se administra una instancia compartida de un bean singleton, y todas las solicitudes de beans con un id o id que coincidan con esa definición de bean dan como resultado que el contenedor Spring devuelva una instancia de bean específica.

Para agregar claridad a esto, el significado detrás de "instancia compartida" se explica en el párrafo que sigue al anterior:

todas las solicitudes y referencias posteriores para ese bean con nombre devuelven el objeto en caché

Cuando se crea un bean singleton, solo se crea una instancia y se almacena en caché de un objeto bean. Esto se refiere solo al bean, no a la clase de la cual el bean puede ser una instancia. Por ejemplo,

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

En esta configuración inventada, "myOtherBean1" y "myOtherBean2" tienen referencias al mismo bean "myBean", por lo tanto, la misma instancia "myPackage.myClass". Si cambia el código para agregar un segundo bean "myPackage.myClass", sería distinto de "myBean".

Para comprender esto completamente, consulte también el otro ámbito de Spring: el prototipo. De la documentación de Spring para Prototype Scope :

El alcance prototipo no singleton de la implementación de bean resulta en la creación de una nueva instancia de bean cada vez que se realiza una solicitud para ese bean específico.

Esto significa que si tuviéramos que usar el mismo Spring XML que el anterior, "myOtherBean1" y "myOtherBean2" recibirían sus propias copias distintas de "myBean", que todavía es solo una instancia de "myPackage.myClass".


El alcance predeterminado de Spring es singleton. Es solo que su idea de lo que significa ser un singleton no coincide con cómo Spring define los singletons.

Si le dice a Spring que haga dos frijoles separados con diferentes identificadores y la misma clase, entonces obtendrá dos frijoles separados, cada uno con un alcance único. Todo el alcance singleton significa que cuando hace referencia a algo con la misma identificación, obtiene la misma instancia de bean.

Así es como la documentación de Spring define el alcance singleton :

Solo se administra una instancia compartida de un bean singleton, y todas las solicitudes de beans con un id o id que coincidan con esa definición de bean dan como resultado que el contenedor Spring devuelva una instancia de bean específica.

El alcance Singleton significa que usar la misma identificación recupera el mismo bean, eso es todo. La prueba de que no hay dos identificadores que hagan referencia a la misma clase obstaculizaría el uso de mapas como beans, y sería complicado al representar las cosas con BeanFactories. Para Spring para la policía, esto implicaría mucho trabajo por poco beneficio, en cambio, confía en que los usuarios sepan lo que están haciendo.

La forma de definir dos nombres para el mismo bean es usar un alias :

En una definición de bean en sí, puede proporcionar más de un nombre para el bean, utilizando una combinación de hasta un nombre especificado por el atributo id, y cualquier número de otros nombres en el atributo de nombre. Estos nombres pueden ser alias equivalentes al mismo bean y son útiles para algunas situaciones, como permitir que cada componente en una aplicación haga referencia a una dependencia común mediante el uso de un nombre de bean que sea específico para ese componente.

Sin embargo, no siempre es adecuado especificar todos los alias donde se define el bean. A veces es deseable introducir un alias para un bean que se define en otra parte. Este es comúnmente el caso en sistemas grandes donde la configuración se divide entre cada subsistema, cada subsistema tiene su propio conjunto de definiciones de objetos. En los metadatos de configuración basados ​​en XML, puede usar el elemento para lograr esto.

Entonces, si agrega un nombre en la configuración del bean:

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

o cree un alias para un bean definido en otra parte:

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

entonces "customer" y "customer2" se referirán a la misma instancia de bean.


El alcance predeterminado de Spring es singleton y creará un objeto para todas las instancias a menos que especifique explícitamente el alcance como prototipo. No ha publicado la configuración de primavera. Por favor publíquelo, le dará una mejor idea.


En SPring, Singleton se refiere a Un bean por contenedor Spring, donde, como en Java, Singleton se refiere a un objeto por cargador de clases.

Entonces Spring Singleton no es lo mismo que Java Singleton. No te confundas entre estos dos.


Estás confundiendo dos conceptos diferentes.

La palabra singleton en primavera se usa para un alcance de bean, lo que significa que el bean se creará solo una vez para toda la aplicación.

El significado habitual de Singleton se refiere al patrón GOF. Es un patrón orientado a objetos que garantiza que solo existirá una instancia de una clase (al menos en el ámbito del cargador de clases).


Estás declarando dos beans de la misma clase. Eso no es lo mismo.

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

E intente acceder a este bean en dos lugares, el número será el mismo. Pero lo que has hecho fue crear dos frijoles separados.

Si quieres comprobar si esto funciona prueba:

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

Este código debe devolver verdadero si es la misma instancia; Pero en SpringTestClass puede agregar la anotación @Scope ("prototipo"). La salida será falsa


Spring Singleton Bean no funciona como Java Singleton.

Si escribimos

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

Si vemos la salida, devolverá 2 instancias diferentes. Según Spring Docs, Bean es singleton, solo se administrará una instancia compartida, y todos los beans de solicitud con un ID o ID que coincida con esa definición de bean. Aquí hay 2 ID diferentes disponibles.

El contenedor de Spring como par de valores clave de gestión, Key como ID / Nombre y el valor es bean.