Rozsah singleton a prototype ve Springu

Spring vytváří beany (instance) a je zodpovědný za jejich životní cyklus. To ale platí pouze v případě, že bean je ve scope singleton. V zásadě můžeme rozdělit beany podle scope na dvě skupiny: singleton a prototype. Singleton znamená, že daná beana (instance) se v kontextu (v aplikaci) vyskytuje pouze v jedné jediné instanci. Pokaždé, když zavoláme metodu getBean(), dostaneme referenci na tu jedinou existující instanci. Pokud je ale scope beany prototype, při každém volání getBean() dostaneme novou instanci.
Nastavení scope se prování při definici dané beany.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean class="cz.vitfo.spring.MyClass01" 
   		init-method="myInit" 
   		destroy-method="myDestroy"
   		scope="singleton">
   </bean>
   <bean class="cz.vitfo.spring.MyClass02" 
   		init-method="myInit" 
   		destroy-method="myDestroy"
   		scope="prototype">
   </bean>
</beans>

Každé beaně jsem nastavil init a destroy metodu (tomuto tématu jsem se věnoval v tomto příspěvku) a scope (rozsah).

MyClass01.java

public class MyClass01 {
	
	public MyClass01() {
		System.out.println("Zavolán konstruktor " + this.getClass().getSimpleName() + ".");
	}
	
	public void myInit() {
		System.out.println("Zavolána metoda init() v " + this.getClass().getSimpleName() + ".");
	}
	
	public void myDestroy() {
		System.out.println("Zavolána metoda destroy() v " + this.getClass().getSimpleName() + ".");
	}
}

MyClass02.java

public class MyClass02 {
	
	public MyClass02() {
		System.out.println("Zavolán konstruktor " + this.getClass().getSimpleName() + ".");
	}
	
	public void myInit() {
		System.out.println("Zavolána metoda init() v " + this.getClass().getSimpleName() + ".");
	}
	
	public void myDestroy() {
		System.out.println("Zavolána metoda destroy() v " + this.getClass().getSimpleName() + ".");
	}
}

Main.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main 
{
    public static void main(String[] args) {
    	ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    	
    	MyClass01 mc11 = context.getBean(MyClass01.class);
    	MyClass01 mc12 = context.getBean(MyClass01.class);
    	MyClass01 mc13 = context.getBean(MyClass01.class);
    	
    	MyClass02 mc21 = context.getBean(MyClass02.class);
    	MyClass02 mc22 = context.getBean(MyClass02.class);
    	MyClass02 mc23 = context.getBean(MyClass02.class);
    	
    	((ConfigurableApplicationContext) context).close();
    }
}

Výsledek spuštění

Zavolán konstruktor MyClass01.
Zavolána metoda init() v MyClass01.
Zavolán konstruktor MyClass02.
Zavolána metoda init() v MyClass02.
Zavolán konstruktor MyClass02.
Zavolána metoda init() v MyClass02.
Zavolán konstruktor MyClass02.
Zavolána metoda init() v MyClass02.
Zavolána metoda destroy() v MyClass01.

Všimněte si, že i když je pro každou ze tříd volána metoda getBean() třikrát, konstruktor třídy MyClass01, která má scope singleton, se zavolá pouze jednou. To samé platí pro metodu init() a destroy(). Pokud jde ale o třídu MyClass02, konstruktor i metoda init() jsou zavolány pokaždé (vždy se vytvoří nová instance). Metoda destroy() se ale nezavolá. Pokud je beana ve scopu prototype, String context ji vytvoří, inicializuje, ale dále ji již nesleduje.

Napsat komentář