Scope and life cycle of Spring Bean

Posted by stewartship on Sun, 23 Jan 2022 14:07:34 +0100

1, Scope and lifecycle

Scope

The scope defines the scope of the bean. When defining a bean in the Spring configuration file, you can flexibly define the scope of the bean by declaring the scope configuration item. For example, when you want the Bean returned by the IOC container to be the same instance each time, you can set the scope to singleton ; When you want the Bean instance returned by the IOC container to be a new instance each time, you can set the scope to prototype . The scope configuration item has five attributes that describe different scopes: singleton,prototype ,request,session,global-session. The description is as follows:

  • singleton : unique bean instance. All beans in Spring are singleton by default.
  • prototype : each request creates a new bean instance.
  • Request: each HTTP request will generate a new bean, which is only valid in the current HTTP request.
  • Session: each HTTP request will generate a new bean, which is only valid in the current HTTP session.

life cycle

The life cycle of a Bean has only four stages (instantiation - > attribute assignment - > initialization - > destruction). Instantiation and attribute assignment correspond to the injection, initialization and destruction of constructor and setter methods. They are two stages that users can customize the extension.

  1. Instantiation
  2. Attribute assignment Populate
  3. Initialization
  4. Destroy Destruction

The main logic is in doCreate(). The logic is very clear, that is, the following three methods are called sequentially, which correspond to the three life cycle stages one by one.
one ️⃣ Createbeaninstance() - > instantiation
two ️⃣ Populatebean() - > attribute assignment
three ️⃣ Initializebean() - > initialize
Viewing the source code can prove the existence of three life cycles: instantiation, attribute assignment and initialization. As for destruction, it is called when the container is closed. See ConfigurableApplicationContext#close() for details.

II Singleton (single case)

  1. By default, Spring creates objects when it reads xml files.
  2. When creating an object (calling the constructor first), init method = ".." will be called The method specified in the property value.
  3. When the object is destroyed, destroy method = "..." will be called The method specified in the attribute value (for example, when container.destroy() is called).
  4. Lazy init = "true" allows this object to be created when it is first accessed, rather than when it is loaded.

In addition, the bean definition of singleton type starts from the container startup to the first request and instantiation. As long as the container does not destroy or exit, a single instance of this type of bean will survive. The typical singleton pattern is like the life cycle of a servlet in a web container.

III Prototype

  1. When Spring reads xml files, it does not create objects.
  2. Every time the object is accessed, the Spring container will create the object and call init method = ".." The method specified in the property value.
  3. When the object is destroyed, the Spring container does not call any methods. Because it is not a singleton, there are many objects of this type. Once the Spring container gives the object to the requester, it will no longer manage the object.

understand:

Just like dividing an apple, declare the scope attribute of the apple bean as prototype. When everyone receives an apple, he is given a new apple. After the apple is sent, others can eat as they like, and when they like, but pay attention to throwing the apple core into the dustbin! For object types that cannot be shared, the scope defined should be set to prototype.

The most typical embodiment is to change the scope of action to prototype when integrating Spring and struts 2.
Because the default scope of Spring is in singleton mode, only one Action object will be created, and the same Action object will be accessed every time, so the data is not safe. Struts 2 requires that each access corresponds to a different Action. Scope = "prototype" can ensure that an Action object is created when there is a request.

4, request

The request, session, and global session types are only applicable to web applications and are usually used with XmlWebApplicationContext.

<bean id ="requestPrecessor"  
	class="...RequestPrecessor" scope="request" />

The Spring container, that is, XmlWebApplicationContext, will be used for each HTTP Request to create a new requestpreprocessor object. When the request ends, the life cycle of the object ends, just like the life cycle of request in java web. When 10 HTTP requests come in at the same time, the container will create 10 new requestpreprocessor instances for these 10 requests, and they will not interfere with each other. In short, request can be regarded as a special case of prototype. Except that the scene is more specific, it has almost the same semantics.

5, session

For web applications, the most common thing to put into a session is the user's login information. For this kind of information put into the session, you can use the following form to formulate the scope as the session:

<bean id ="userPreferences"  
	class="...UserPreferences" scope="session" />

The Spring container will create its own brand-new UserPreferences instance for each independent session, which will last longer than the bean of the request scope. There is no difference in other aspects, just like the life cycle of the session in the java web.

6, global session

<bean id ="userPreferences" 
	class="...UserPreferences" scope="globalsession" />

Global session is meaningful only when it is applied in the web application based on porlet. It maps to the global session of porlet. If this scope is used in the web application of ordinary servlet, the container will treat it as the scope of ordinary session.

7, scope configuration

one ️⃣ xml method: specify scope when configuring bean s

two ️⃣ Annotation method: the premise is that Spring is configured for annotation

VIII bean initialization timing

After getting familiar with the scope of Spring container managed beans, we have to think about a question: when are beans instantiated? bean objects are instantiated at the following two times:

  1. When the Spring container starts.
  2. When calling getBean().

So when the bean object is instantiated has something to do with the scope of the bean. In order to clearly see the instantiation of the bean object, modify the code of the PersonServiceBean class as follows:

public class PersonServiceBean implements PersonService {    
  public PersonServiceBean() {  
    System.out.println("I was instantiated");   
  }     
  @Override    
  public void save() {     
    System.out.println("I am save()"); 
  }
}

one ️⃣ When the Spring configuration file - beans The contents of XML are:

 <?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.xsd">

<bean id="personService"
	class="cn.service.impl.PersonServiceBean"></bean> 

</beans>

That is, when the scope of the bean is singleton, modify the code of the SpringTest class as follows:

public class SpringTest {     
   @Test    
    public void test() {        
       // Instantiate the Spring container   
       ApplicationContext ctx = 
       	new ClassPathXmlApplicationContext("beans.xml");
    } 
}

Execute test() and output:

I was instantiated

This shows that when the scope of the bean is singleton, the bean object is created when the Spring container is started. That is, by default, the bean will be initialized when the container starts, but you can also specify the lazy init = "true" of the bean node to delay the initialization of the bean. At this time, the bean is initialized only when the bean is obtained for the first time.
For example, the Spring configuration file beans The content of the XML is changed to:

<?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.xsd">     

<bean id="personService"
	class="cn.service.impl.PersonServiceBean" 
		lazy-init="true"></bean>

</beans>

Lazy init = "true" specifies not to instantiate this bean when the Spring container starts. At this point, execute test(), and the sentence "I have been instantiated" will not be output. At this time, you can only modify the code of the SpringTest class to:

public class SpringTest {     
    @Test   
    public void test() {        
     //Instantiate the Spring container
     ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
     //Get bean from Spring container
     PersonService personService = (PersonService) ctx.getBean("personService");
    } 
}

Execute test() again to output this sentence:

I was instantiated

If you want to apply deferred initialization to all beans, you can set default lazy init = "true" on the root node beans, as follows:

<?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.xsd" 
default-lazy-init="true">     
...... 
</beans>

two ️⃣ When the Spring configuration file - beans The contents of XML are:

<?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.xsd">   
  
<bean id="personService"
	class="cn.service.impl.PersonServiceBean" 
			scope="prototype"></bean> 

</beans>

That is, when the scope of the bean is prototype, if the code of the SpringTest class is:

public class SpringTest {     
  @Test    
  public void test() {        
    // Instantiate the Spring container 
    ApplicationContext ctx = 
    	new ClassPathXmlApplicationContext("beans.xml"); 
  } 
}

Execute test() without outputting the sentence: "> I'm instantiated". This shows that when the scope of the bean is prototype, the bean object will not be created when the Spring container is started. However, if you change the code of the sprin gt est class to:

public class SpringTest {     
    @Test    
     public void test() {        
       // Instantiate the Spring container
       ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); 
       // Get bean from Spring container
       PersonService personService = (PersonService) ctx.getBean("personService"); 
  }
}

Execute test() again and output the following sentence:

I was instantiated

It is confirmed that when the scope of the bean is prototype, the bean object will be created when calling getBean().

9, Specify the initialization method and destruction method of the bean

In order to initialize some resources when the bean is initialized, the code of the PersonServiceBean class can be modified as follows:

public class PersonServiceBean implements PersonService {
    public void init() {
        System.out.println("Initialize some resources");
    }
    public PersonServiceBean() {
        System.out.println("I was instantiated");
    }
    @Override
    public void save() {
        System.out.println("I am save()");
    }
}

In this way, the purpose is to execute the init() of the PersonServiceBean object after the Spring container initializes the object. To achieve this, simply modify the Spring configuration file - beans The contents of XML are:

<?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.xsd">    
 
<bean id="personService"
	class="cn.service.impl.PersonServiceBean" 
lazy-init="false" init-method="init" />

</beans>

If the code of the SpringTest class is:

public class SpringTest {
    @Test
    public void test() {
        // Instantiate the Spring container     
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
    }
}

Execute test() and output:

Now I want to release or close some resources when the bean is destroyed. To achieve this, you can modify the code of the PersonServiceBean class as follows:

public class PersonServiceBean implements PersonService {
    public void init() {
        System.out.println("Initialize some resources");
    }
    public PersonServiceBean() {
        System.out.println("I was instantiated");
    }
    @Override
    public void save() {
        System.out.println("I am save()");
    }
    public void destroy() {
        System.out.println("Release initialized resources");
    }
}

When was the bean object destroyed? The answer is: if it is not deleted artificially, the bean will always be in the Spring container by default, that is, the bean will be destroyed only after the Spring container is closed. Next, modify the Spring configuration file - beans The content of the XML.

<?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.xsd">     

<bean id="personService" class="cn.service.impl.PersonServiceBean" 
lazy-init="false" init-method="init" destroy-method="destroy" /> 

</beans>

Finally, modify the test class - springtest Java is:

public class SpringTest {
    @Test
    public void test() {
        // ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); 
        // Instantiate the Spring container         
        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        // Close the Spring container normally  
        ctx.close();
    }
}

Execute test() and output:

This is the life cycle of Spring managed beans.

Topics: Java Spring