spring - docs - ¿Cuál es la diferencia entre el frijol singleton y el prototipo?
taglib spring jsp (12)
Soy nuevo en la primavera y leí esto:
Básicamente, un bean tiene ámbitos que definen su existencia en la aplicación.
Singleton: significa definición de bean único para una instancia de un solo objeto por contenedor Spring IOC.
Prototipo: significa una sola definición de bean para cualquier número de instancias de objetos.
Entonces, ¿qué es la "instancia de objeto".
- El alcance de Singleton es el predeterminado.
- Los beans Singleton se crean durante la inicialización del contexto de la aplicación y el mismo bean se devuelve siempre.
- Prototipo de frijol se crea cuando se llama. Cada vez que se llama obtenemos un nuevo objeto.
Nota: Bean con cualquier alcance se creará si es referido por otros beans y se llama utilizando el contexto de la aplicación.
Código de ejemplo para comprobar esto.
public class PrototypeClass {
PrototypeClass()
{
System.out.println("prototype class is created"+this.toString());
}
}
Esto imprimirá el texto relevante cuando se invoque el constructor.
para el siguiente código
for(int i=0;i<10;i++) {
PrototypeClass pct= (PrototypeClass) context.getBean("protoClass");
}
se crea la clase de prototipoSpring.PrototypeClass@29774679 se crea la clase de prototipoSpring.PrototypeClass@3ffc5af1 se crea la clase de prototipoSpring.PrototypeClass@5e579. is createdSpring.PrototypeClass@ae45eb6 se crea la clase de prototipoSpring.PrototypeClass@59f99ea se crea la clase de prototipoSpring.PrototypeClass@27efef64. Se crea la clase de prototipoSpring.PrototypeClass@47f7fd0e6. Se crea la clase de prototipo.
Definición de frijol es
<bean id="protoClass" class="Spring.PrototypeClass" scope="prototype</bean>
Ahora cambié el alcance en la definición de bean a singleton. Se llama al constructor solo una vez durante la inicialización del contexto. Luego eliminé el atributo de alcance y observé el mismo comportamiento que singleton.
Agregando a lo anterior ... no se confunda con el singleton java. De acuerdo con la especificación JAVA, singleton significa que solo se creará una instancia de ese bean por JVM. pero en primavera, singleton significa que se creará una instancia para ese bean en particular por contexto de aplicación. por lo tanto, si su aplicación tiene más de un contexto, aún puede tener más de una instancia para ese bean.
Ambos son patrones de diseño creacional.
Singleton, creará una nueva instancia en la primera llamada y la devolverá en llamadas posteriores.
Prototipo devolverá una nueva instancia cada vez.
Quiero agregar información adicional que pueda ayudarnos a descubrir el significado de "instancia de objeto" en las oraciones mencionadas. Este párrafo de Spring Doc intenta definir "instancia de objeto":
Cuando crea una definición de bean, crea una receta para crear instancias reales de la clase definida por esa definición de bean . La idea de que una definición de bean es una receta es importante, porque significa que, al igual que con una clase, puede crear muchas instancias de objetos a partir de una sola receta.
Por lo tanto, como se mencionó en la sección anterior, cada definición de bean puede considerarse como una Clase (en términos de Orientado a Objetos). De acuerdo con los datos que definió en él (como el alcance, ...) esta clase (o definición de bean) puede tener solo una instancia de objeto (el alcance de singleton por solo una instancia compartida) o cualquier número de instancias de objeto (por ejemplo, Prototipo del alcance mediante la creación de una nueva instancia de bean cada vez que se realiza una solicitud para ese bean específico).
Si el alcance se establece en singleton, el contenedor Spring IoC crea exactamente una instancia del objeto definido por esa definición de bean. Esta instancia única se almacena en un caché de dichos beans singleton, y todas las solicitudes y referencias posteriores para ese bean con nombre devuelven el objeto almacenado en caché.
El alcance predeterminado siempre es singleton; sin embargo, cuando necesita una y solo una instancia de un bean, puede establecer la propiedad de alcance en singleton
La diferencia entre Singleton y Prototype es el alcance del Prototipo para todos los beans completos del estado y el alcance Singleton para los beans sin estado.
Simplemente busquemos esto a través del Código.
A continuación se muestra un bean TennisCoach con alcance de singleton
predeterminado
@Component
@Scope("singleton")
public class TennisCoach implements Coach {
public TennisCoach(){
}
@Autowired
public void setFortuneService(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Practice your backhand volley";
}
@Override
public String getDailyFortune() {
return "Tennis Coach says : "+fortuneService.getFortune();
}
}
A continuación se muestra un Bean TennisCoach con prototipo de alcance.
@Component
@Scope("prototype")
public class TennisCoach implements Coach {
public TennisCoach(){
System.out.println(">> TennisCoach: inside default constructor");
}
@Autowired
public void setFortuneService(FortuneService fortuneService) {
System.out.println(">> Tennis Coach: inside setFortuneService");
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Practice your backhand volley";
}
@Override
public String getDailyFortune() {
return "Tennis Coach says : "+fortuneService.getFortune();
}
}
La siguiente es una clase principal:
public class AnnotationDemoApp {
public static void main(String[] args) {
// read spring config file
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
// get the bean from the spring container
Coach theCoach = context.getBean("tennisCoach",Coach.class);
Coach alphaCoach = context.getBean("tennisCoach",Coach.class);
// call a method on the bean
System.out.println("Are the two beans same :" + (theCoach==alphaCoach));
System.out.println("theCoach : " + theCoach);
System.out.println("alphaCoach: "+ alphaCoach);
context.close()
}
}
Para el alcance de singleton la salida es:
Are the two beans same :true
theCoach : com.springdemo.TennisCoach@2a53142
alphaCoach: com.springdemo.TennisCoach@2a53142
Para el alcance del prototipo la salida es:
Are the two beans same :false
theCoach : com.springdemo.TennisCoach@1b37288
alphaCoach: com.springdemo.TennisCoach@1a57272
Espero que esto responda a su pregunta. :RE
Singleton es la misma instancia en toda la aplicación
Prototype es una nueva instancia para cada nueva solicitud de getBean
Singleton: si el alcance se establece en singleton, el contenedor Spring IoC crea exactamente una instancia del objeto definido por esa definición de bean. Esta instancia única se almacena en un caché de dichos beans singleton, y todas las solicitudes y referencias posteriores para ese bean con nombre devuelven el objeto almacenado en caché.
Prototipo: si el alcance está configurado como prototipo, el contenedor Spring IoC crea una nueva instancia de bean del objeto cada vez que se realiza una solicitud para ese bean específico. Como regla general, use el alcance del prototipo para todos los beans de estado completo y el alcance de singleton para los beans sin estado.
Spring garantiza exactamente una instancia de bean compartido para el ID dado por contenedor IoC, a diferencia de Java Singletons, donde Singleton codifica el alcance de un objeto de tal manera que una y solo una instancia de una clase particular se creará por ClassLoader.
Alcance de Singleton: con el alcance de Singleton, una y solo una instancia de un bean se crea con la definición de bean proporcionada y para las solicitudes subsiguientes del mismo bean, el contenedor Spring devolverá la misma instancia.
De la documentación de primavera:
... cuando define una definición de bean y tiene un ámbito de singleton, el contenedor Spring IoC crea exactamente una instancia del objeto definido por esa definición de bean. Esta instancia única se almacena en un caché de dichos beans de singleton, y todas las solicitudes y referencias posteriores para ese bean con nombre devuelven el objeto en caché ...
Ejemplo: Digamos que hemos definido una cuenta bean como se muestra a continuación:
<bean id="accountDao" class="" />
Y otros dos frijoles, que usa este frijol de cuenta.
<bean id="someBean" ref="accountDao" />
<bean id="anotherBean" ref="accountDao" />
Spring inicialmente creará accountDao
bean accountDao
y lo almacenará en caché. Y luego, para algunos someBean
y otro anotherBean
, proporcionará la misma instancia de accountDao
.
Nota: Si no se especifica ningún ámbito con la definición de bean, Singleton es el ámbito predeterminado.
Alcance del prototipo: Para el alcance del prototipo, para cada solicitud del bean, se creará y se devolverá una nueva instancia del bean. Esto es similar a llamar a un nuevo operador en java para una clase.
Ejemplo: Digamos que hemos definido una cuenta bean como se muestra a continuación:
<bean id="accountDao" class="" scope="prototype"/>
Y otros dos frijoles, que usa este frijol de cuenta.
<bean id="someBean" ref="accountDao" />
<bean id="anotherBean" ref="accountDao" />
Para algunos Bean y otro Bean, Spring devolverá dos instancias separadas del objeto accountDao.
Una diferencia importante es que, para el alcance del prototipo, Spring no administra el ciclo de vida completo del bean, el código de cliente debe realizar la limpieza.
De la documentación de primavera:
Spring no gestiona el ciclo de vida completo de un bean prototipo: el contenedor crea una instancia, configura y, por lo demás, ensambla un objeto prototipo y se lo entrega al cliente, sin registro adicional de esa instancia de prototipo. Por lo tanto, aunque los métodos de devolución de llamada de ciclo de vida de inicialización se invocan en todos los objetos, independientemente del alcance, en el caso de los prototipos, las devoluciones de llamada de ciclo de vida de destrucción configurada no se llaman. El código del cliente debe limpiar los objetos del ámbito del prototipo y liberar los recursos costosos que contienen los prototipos de bean.
Alcance de prototipo: se crea un nuevo objeto cada vez que se inyecta.
Alcance de Singleton: el mismo objeto se devuelve cada vez que se inyecta.
El alcance de prototipo se usa para todos los beans que son con estado, mientras que el alcance de singleton se debe usar para los beans sin estado. Déjame explicarte con mi ejemplo. Por favor, copie y ejecútelo usted mismo para obtener una comprensión clara. Considere un entrenador de interfaz.
public interface Coach {
public String getDailyWorkout();
public String getDailyFortune();
}
Tenemos otra clase llamada TrackCoach que implementa Coach.
public class TrackCoach implements Coach {
private FortuneService fortuneService;
public TrackCoach(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Run a hard 5k";
}
@Override
public String getDailyFortune() {
return "Just Do it: " + fortuneService.getFortune();
}
}
Ahora hay una interfaz FortuneService.
public interface FortuneService {
public String getFortune();
}
Es implementado por nuestra clase HappyFortuneService.
public class HappyFortuneService implements FortuneService {
@Override
public String getFortune() {
return "Today is your lucky day!";
}
}
Conectemos las dos clases e inyectemos un objeto bean de una clase en otra usando Xml. Realicemos inyección de dependencia. Tenga en cuenta que también podemos hacer esto utilizando la anotación java.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Define your beans here -->
<!-- define the dependency -->
<bean id = "myFortuneService"
class = "com.luv2code.springdemo.HappyFortuneService">
</bean>
<bean id = "myCoach"
class = "com.luv2code.springdemo.TrackCoach"
scope = "singleton">
<!-- set up construction injection -->
<constructor-arg ref = "myFortuneService" />
</bean>
</beans>
Tenga en cuenta que scope = singleton
.
Ahora definamos nuestro BeanScopeDemoApp, que tiene nuestro método principal.
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanScopeDemoApp {
public static void main(String[] args) {
// load the spring configuration file
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("beanScope-applicationContext.xml");
// retrieve bean from spring container
Coach theCoach = context.getBean("myCoach", Coach.class);
Coach alphaCoach = context.getBean("myCoach", Coach.class);
// check if they are the same
boolean result = (theCoach == alphaCoach);
// print out the results
System.out.println("/nPointing to the same object: " + result);
System.out.println("/nMemory location for theCoach: " + theCoach);
System.out.println("/nMemory location for alphaCoach: " + alphaCoach +"/n");
// close the context
context.close();
}
}
Una vez que ejecute el código anterior, verá los siguientes resultados:
Pointing to the same object: true
Memory location for theCoach: com.luv2code.springdemo.TrackCoach@16515bb7
Memory location for alphaCoach: com.luv2code.springdemo.TrackCoach@16515bb7
Apunta al mismo objeto y ocupa la misma ubicación de memoria después de llamarlo dos veces. Ahora cambiemos el scope = prototype
en nuestro archivo Xml, guárdelo y ejecute BeanScopeDemoApp nuevamente.
Verás los siguientes resultados:
Pointing to the same object: false
Memory location for theCoach: com.luv2code.springdemo.TrackCoach@6d4d203d
Memory location for alphaCoach: com.luv2code.springdemo.TrackCoach@627fbcda
Apunta al objeto diferente y ocupa las diferentes ubicaciones de memoria después de llamarlo dos veces. Esta sería una ilustración gráfica de lo que acabo de decir.
Alcance de prototipo = Se crea un nuevo objeto cada vez que se inyecta / busca. Utilizará el new SomeClass()
cada vez.
Singleton scope = (Predeterminado) El mismo objeto se devuelve cada vez que se inyecta / busca. Aquí se instanciará una instancia de SomeClass
y luego se devolverá cada vez.
Ver también: