Scope of the spring bean

Source: Internet
Author: User

The previous article described in more detail the configuration of bean dependencies in various cases, but has not explained the scope of this property. This article will study together. This article demonstrates the code

When we configure the definition of a bean in an XML configuration file, we can assume that we have configured a template that can be used to generate many objects to satisfy the dependencies of the entire application, and we can also configure the scope of the object.

Scope can be understood as a qualified scenario where an object in the SPRINGIOC container should be located, or the object's survival space, that is, when the IOC container generates and assembles the objects before they enter the appropriate scope, the container will typically destroy those objects after the object is no longer qualified for those scopes.

So far, spring has provided six types of scope:

1. Singleton represents a singleton in a spring container that always returns a unique instance when the bean is obtained through the spring container

2. prototype means that each time a bean is obtained, a new object will be generated

3. Request is valid for one HTTP request (web App only)

4. Session is valid within a user session (web app only)

5. The global Session is similar to the above, but is used on servers in mobile devices.

6. Globalsession is valid for a global session (Web app only)

In general, the first two scopes are sufficient to meet the requirements, the latter to be used in the Web container, the default scope is singleton.

Note: spring3.0 is available SimpleThreadScope , but is not registered by default.

Single example basic

Singleton is the default scope used by the spring container. Note that the concepts described in Singleton and design patterns are different. In design mode, there is only one instance of each ClassLoader class, and this means that each spring container has only one instance for a beandefinition.

See note:


The code set in the following section describes Singleton and prototype .

Lazy Loading

By default, singleton beans are initialized during the spring container initialization, and the benefit is that configuration errors can be discovered as early as possible.

But if necessary, you can cancel this mechanism, using the bean tag's Lazy-init attribute, as follows:


<bean id= "lazy" class= "Com.foo.ExpensiveToCreateBean" lazy-init= "true"/>

You can also cancel the preload behavior in the configuration File root tab beans using the following configuration:

<beans default-lazy-init= "true" >    <!--no beans'll be pre-instantiated ...--></beans>

Prototype

Scope is a prototype bean definition and always re-creates a completely new object every time it is needed, whether it is the need for dependency injection, Or the Getbean method that calls ApplicationContext. As stated:


Unlike other types of scopes, spring does not fully manage the life cycle of scope prototype, and the spring container simply instantiates, configures, and assembles an instance to the customer without further recording its state. The spring container executes all of the bean's initialization methods, but for a prototype bean, its destruction life-cycle function is not executed, so the expensive resources it holds will need to be freed by the client itself.

The following code further understands that the first is Client1 and client2 two classes, they are exactly the same, and Accoutdao is an empty class and nothing:

Package com.test.scope.si; /**  * @Description: There are three Accoutdao references, their scope is default, singleton (Singleton), prototype (prototype) * omitted get Set method */public class Client1 {    private Accoutdao Accoutdao;    Private Accoutdao Accoutdaob;    Private Accoutdao Accoutdaoc;       @Override public    String toString () {       return "Client1 [accoutdao=" + Accoutdao + ", accoutdaob=" + Accoutdaob + ", Accoutdaoc= "+ Accoutdaoc +"] ";    }}

Here is the configuration file:

<?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 "> <!--definition three Accoutdao beans in turn default configuration singleton prototype-- <bean id= "Account1" class= "Com.test.scope.si.AccoutDao" ></bean> <bean id= "Account2" class= "com.test. Scope.si.AccoutDao "scope=" singleton "></bean> <bean id=" Account3 "class=" Com.test.scope.si.AccoutDao " Scope= "Prototype" ></bean> <!--define Client1 Bean and Client2 bean their definition is exactly the same, here just to illustrate Singleton and Prototyp  E difference They all have three dependencies, which are the beans defined above--<bean id = "C1A" class= "Com.test.scope.si.Client1" > <property Name= "Accoutdao" ref= "Account1" ></property> <property name= "Accoutdaob" ref= "Account2" ></propert y> <property name= "accoutDaoc "ref=" Account3 "></property> </bean> <bean id =" C2A "class=" com.test.scope.si.Client 2 "> <property name=" Accoutdao "ref=" Account1 "></property> <property name=" Accoutdaob "ref=     "Account2" ></property> <property name= "Accoutdaoc" ref= "Account3" ></property> </bean> </beans>


Here is the test program:

Package com.test.scope; Import Org.springframework.context.applicationcontext;import Org.springframework.context.support.ClassPathXmlApplicationContext;  public class Testmain {public    static void Main (string[] args) {             ApplicationContext context = new CLASSPATHXMLAPPL Icationcontext ("Allbean.xml");              The test scope is singleton and prototype, and the following three beans are defined in turn as default, Singleton, and prototype.       //Note that the  printed value is the same and different from the C1A and c2a that are behind it       System.out.println (Context.getbean ("Account1"));       System.out.println (Context.getbean ("Account2"));       System.out.println (Context.getbean ("Account3"));        Note the following differences, you can see that the value of ACCOUTDAOC is always different. The others are consistent with the print above.        System.out.println (Context.getbean ("C1A"));       System.out.println (Context.getbean ("C2A"));           } }

Test results to match expectations:

Other scope

In addition to the above two scopes, there are request, session and global session three scopes, which are used in the web environment, otherwise they will throw an exception.

The scope of its bean is similar to the above, and the difference is their meaning. meaning see the beginning of the brief description, the specific code examples see the next section, below the above three types of scope of the test environment.

To test the three scopes that require a Web project, the Web project deployment is more complex, and this article integrates spring and servlet into a simple test based on spring's official documentation and some online information, and the following configuration is configured in XML. The corresponding servlet then obtains the dependency from the container in the Init method:

<context-param>       <param-name>contextConfigLocation</param-name>       <param-value>/ web-inf/classes/weballbean.xml</param-value>    </context-param>     <listener>       < Listener-class>org.springframework.web.context.contextloaderlistener</listener-class>    </ listener>     <listener>        <listener-class> Org.springframework.web.context.request.requestcontextlistener</listener-class>    </listener>

Manual injection of dependencies in the Init method in the servlet:

public void init (ServletConfig config) throws servletexception {       //TODO Auto-generatedmethod stub       super.init ( config);       Webapplicationcontext ApplicationContext = Webapplicationcontextutils.getrequiredwebapplicationcontext (This              . Getservletcontext ());       c = Applicationcontext.getbean ("c3a", client3.class);       System.out.println ("Iniiiiiii-------------");    }


Note: You need to introduce the dependent packages for AOP.

There are a few other ways:

Servlet Proxy: http://blog.csdn.net/xwl617756974/article/details/7451773

Support for Autowire SERVLET:HTTP://WWW.TUICOOL.COM/ARTICLES/32U3QR

Also on the scope of spring and the role of Requestcontextlistener

Different scope dependencies

There may be dependencies in each bean in the spring container, and the scope may vary between the dependent beans. There may be a problem with dependencies between different scopes. The main is the following two kinds:

Singleton relies on prototype;

Reques, session, application as dependency.

Singleton Dependent prototype

Dependencies are ubiquitous, and when this happens, because Singleton is instantiated only once, the prototype beans it relies on are only once set to be dependent. This is sometimes not what we want.

Assume that scope for a is singleton,b for prototype, and a depends on B. When some of the methods of A are called, a new collaboration of B is required. The problem arises when the bean defines the method that depends on it.

There are three kinds of solutions:

Spring Interface Manual Injection

When invoking the relevant method, manually re-injecting the prototype bean, which allows the bean to implement the Applicationcontextaware interface, get a reference to the spring container, and get the bean from it. The disadvantage of this is that it is coupled with the spring interface. The sample code is as follows:

Defines a brand-new class CLIENTFORSP, the method inside the Testone and testtwo are printing itself, the difference is Testone did the re-injection processing, there are two accoutdao types of prototype rely on to compare, Accoutdao and above are the same:

Package com.test.scope.sid; Import Org.springframework.beans.beansexception;import Org.springframework.context.applicationcontext;import Org.springframework.context.ApplicationContextAware; Import Com.test.scope.si.AccoutDao; /** * @Description: Test singleton dependent prototype, implement Applicationcontextaware interface, get reference to bean factory * Two dependent fields are prototype, * method Testone and T Esttwo are required to rely on field assistance. * Method Testone each call to retrieve the bean, so each time it is a new bean. * Method Testtwo is not. * */public class CLIENTFORSP implements Applicationcontextaware{private Accoutdao accoutdao;private AccoutDao ACCOUTDAO1; Private ApplicationContext context;    public void Testone () {This.setaccoutdao (Createaccountdao ());  System.out.println (this);}   public void Testtwo () {System.out.println (this);} Public Accoutdao Getaccoutdao () {return accoutdao;} public void Setaccoutdao (Accoutdao accoutdao) {This.accoutdao = Accoutdao;} Public Accoutdao GetAccoutDao1 () {return accoutDao1;} public void SetAccoutDao1 (Accoutdao accoutDao1) {this.accoutdao1 = AccoutdAO1;} Public Accoutdao Createaccountdao () {return Context.getbean ("Account3", Accoutdao.class);} @Overridepublic String ToSt   Ring () {return "clientforsp [accoutdao=" + Accoutdao + ", accoutdao1=" + AccoutDao1 + "]";}  @Overridepublic void Setapplicationcontext (ApplicationContext arg0) throws beansexception {this.context = arg0;}}

The configuration file is as follows:

<!--definition  CLIENTFORSP dependent on two prototype beans, but manually injected with the spring interface in Clientforsp method testone      = "<bean" class= "Com.test.scope.sid.ClientForSp" >        <property name= "Accoutdao" ref= "Account3" ></property>        <property name= "AccoutDao1" ref= "Account3" ></property>    </bean>


Test the code as follows, first calling the two Testtwo method (without re-injecting the dependency), and then calling the Testone method (re-injecting the dependency):

CLIENTFORSP SP1 = Context.getbean ("Csp1", clientforsp.class);       Sp1.testtwo ();       Sp1.testtwo ();       System.out.println ();        Sp1.testone ();       Sp1.testone ();


The test results are as follows, two calls to the Testtwo method print exactly the same, and then call the Testone method to see that the Accoutdao reference is different each time, as expected:


Lookup methodinjection

The spring container can overwrite (override) a method of the bean that it manages (the bean it finds as the return value of the bean) by locating its managed named Bean as the return value. Use this to solve these problems. The method overrides the form of dynamically generated bytecode. The overridden method can be abstract or non-abstract and requires no parameters.

The method signature is as follows:

<public|protected> [abstract] <return-type> themethodname (no-arguments);

To solve the above problem, you need to use the Bean label <lookup-method> Sub-label, the sample code is similar to the above, only the configuration is different, configured as follows:

<!--define  CLIENTFORSP, which relies on two prototype beans, uses the Lookup-method method to re-inject the new prototype bean     every time the testone is called-- <bean id = "CSP2" class= "com.test.scope.sid.ClientForSp" >        <lookup-method name= "Createaccountdao" bean= " Account3 "/>        <property name=" AccoutDao1 "ref=" Account3 "></property>    </bean>

The test code and the results are no longer repeating.

Arbitrary methodreplacement

This is a less common approach. An additional class is required to implement the Methodreplacer interface, so the name Incredibles is used to do the method substitution.

Also need to use the Bean tag's <lookup-method> sub-label <replaced-method>, and the sample code is similar to the above, note the implementation of configuration and Methodreplacer:

<!--define  CLIENTFORSP, rely on two prototype beans, use Replaced-method method, Force replace  Createaccountdao Method-     < Bean id = "CSP3" class= "com.test.scope.sid.ClientForSp" >        <replaced-method name= "Createaccountdao" Replacer = "Myreplacer" ></replaced-method>        <property name= "Accoutdao" ref= "Account3" ></property>        <property name= "AccoutDao1" ref= "Account3" ></property>    </bean>        <bean id = " Myreplacer "class=" Com.test.scope.sid.MyAccountCreateor "/>

The meaning of the public class Myaccountcreateor implements Methodreplacer {          /**      * parameter is the method object, method, and parameter that was called */    @ Override Public    Object Reimplement (Object arg0, Method arg1, object[] arg2) throws Throwable {       SYSTEM.OUT.PRINTLN ("replaced");       return new Accoutdao ();    } }


Test code and analysis are not in the repeating.

Reques, session, application as dependency.

When scope is request, session, and globalsession beans are injected into other ranges of beans as dependencies, a similar singleton-dependent prototype problem arises. In this case, just use the child label of the Bean <aop:scoped-proxy/>.

As follows:

<!--an HTTP request Bean exposed as a proxy-to    <bean id= "account4" class= "Com.test.scope.si.AccoutDao" SCOP e= "Request" >        <!--instructs the container to proxy the surrounding bean--and        <aop:scoped-proxy/>& Lt;/bean> <!--a singleton-scoped bean injected with the above beans-     <bean id = "C3A" class= "Com.test.s Cope.si.Client3 ">        <property name=" Accoutdao "ref=" Account4 "></property>    </bean>

Although the code is simple, understand the problem. Since C3A's scope is singleton, it is initialized only once, and its dependent Accoutdao scope is only injected once, when it is different HttpRequest comes, bean "c3a" The Accoutdao dependence is always the same, which is certainly wrong. So add the <aop:scoped-proxy/> sub-tag and tell the spring container to use an AOP proxy to generate different Accoutdao objects for different request. The technique of dynamically generating bytecode is generally used. If you do not use the <aop:scoped-proxy/> tag, start the Times wrong.

The following uses specific code to demonstrate the difference between the scope of the request and session using an AOP agent. The code requires a Web environment and the deployment of the environment is shown above. Here a bean is configured with two dependencies, followed by Requset Proxy, session proxy.

The configuration is as follows:

     <!--an HTTP request Bean exposed as a proxy-to    <bean id= "account4" class= "Com.test.scope.si.AccoutDao" SCOP e= "Request" >        <!--instructs the container to proxy the surrounding bean--and        <aop:scoped-proxy/>< C4/></bean>       <!--an HTTP session bean exposed as a proxy--    <bean id= "account5" class= "Com.test.s Cope.si.AccoutDao "scope=" Session ">        <!--instructs the container to proxy the surrounding bean--        < aop:scoped-proxy/>    </bean>          <!--a singleton-scoped bean injected with the above beans     - <bean id = "C3A" class= "Com.test.scope.si.Client3" >        <property name= "Accoutdao" ref= "Account4" ></ property>        <property name= "AccoutDao1" ref= "account5" ></property>    </bean>


Class Client3 test is a standard JavaBean, two fields and above the dependency correspondence, here does not repeat. The test code is in a servlet, and the following is its Doget method:

if (c! = null) {           System.out.println ("Request agent is not the same every time" +c.getaccoutdao ());           SYSTEM.OUT.PRINTLN ("session proxy different sessions not the same" +c.getaccoutdao1 ());        } else {           System.out.println ("null");       }
Deploy the above code to tomcat, and then use different browsers to access two times, different browsers to simulate different sessions, the test results are as follows:


The above test results were first accessed two times by a Computer browser and accessed two times using a mobile browser. First, each access request relies on a different value. Second, the same browser is dependent on the session, different browsers are not the same. The above meets the expected results.

End

This article provides a more detailed description of the spring Bean's scope property, with detailed sample test code. The dependency between scope and scope, especially when it comes to the scope of the web, I spend more time deploying the environment. The scope also lacks a custom scope section, which is not discussed for the moment. We look forward to common progress. This article demonstrates the code

Scope of the spring bean

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.