Spring 5 Chinese parsing core – bean scope of IOC container

Time:2020-11-23

When you create abeanWhen defining, you can create a template (recipe) throughbeanDefine the class definition to create a real instance.beanThe concept of definition as a recipe is important because it means that, just like using classes, you can create multiple object instances from a single recipe.

You can not only control to insert from specificbeanDefine the various dependencies and configuration values in the created object, and you can also control thebeanDefines the scope of the created object. This method is very useful and flexible, because you can choose the scope of the object created by configuration without having to consider the scope of the object at the Java class level.beanAbility to define deployment to one or more scopes.SpringThe framework supports six scopes, and four are used onlywebEnvironmental Science. You can create custom scopes.

The following table describes the scope of the support:

Scope Description
singleton (default) limits the scope of a single bean definition for each spring IOC container to a single object instance.
prototype Limits the scope of a single bean definition to any number of object instances
request Limits the scope of a single bean definition to the life cycle of a single HTTP request. That is, each HTTP request has a bean instance created. Only valid in spring ApplicationContext web container
session Limit the scope of a single bean definition to the HTTP session lifecycle. Only valid in spring ApplicationContext web container
application Limit the scope of a single bean definition to the ServletContext lifecycle. Only valid in spring ApplicationContext web container
websocket Limit a single bean definition to the websocket lifecycle. Only valid in spring ApplicationContext web container

fromSpring3.0After, the thread security scope is valid, but it is not registered by default. For more information, see the documentationSimpleThreadScope。 For more information on how to register and customize scopes, see custom scopes

1.5.1 singleton bean scope

Single casebeanOnly one shared instance is managed by the container, and all pairs havebeanDefine matchingIDOfbeanWill cause the specificbeanInstance bySpringContainer returns. In another way, when you define abeanAnd its scope is a singleton,Spring IoCContainer creation viabeanAn instance of a defined object definition. This singleton is stored in the cache and named forbeanAll requests and references for are returned as cached objects. The following image shows a single examplebeanHow scopes work:

Spring 5 Chinese parsing core - bean scope of IOC container

SpringSingle example ofbeanConcept and inGoFThe singleton patterns in the design pattern book are different.GoFThe scope corresponding to the singleton hard coding, for example: only one object instance of a specific class is available for eachClassLoaderCreate only one object instance. It is better toSpringThe scope of the singleton is described as each container and eachbean(Note:GoFSingleton in design patternbeanIt’s about the differenceClassLoaderYes, andSpringThe singleton of is for different container levels). This means that if theSpringContainer defines abeanSpringContainer passing throughbeanCreates an instance of the defined class. staySpringThe singleton scope in is the default. To define abeanFor example, you can define abeanThis is similar to the following example:

<bean id="accountService" class=" com.something.DefaultAccountService / >
1.5.2 prototype scope

Non singleton prototypebeanThe scope deployment result is specified in each requestbeanYou will create abeanexample. That is,beanInjected into othersbeanOr through the containergetBean()Method calls create a newbean。 Typically, prototype scope is used for all stateless beans and statefulbeanUse singletonbeanScope.

The following figure illustrates thisSpringSingleton scope of:

Spring 5 Chinese parsing core - bean scope of IOC container

Data access object(DAO)It is not usually configured as a prototype because typicallyDAONo session state is maintained. We can reuse the core of the singleton diagram more easily.

The following example is shown inXMLDefine a prototype inbean

<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>

Compared with other scopes,SpringThere is no management prototypebeanThe complete life cycle of. The container instantiates, configures, or otherwise assembles the prototype object and hands it over to the client without further recording the prototype instance. Therefore, although the initialization lifecycle callback function is called back on all objects regardless of scope,In the prototype case, the configuration destroy lifecycle callback is not called back。 The client code must clear the objects in the scope of the prototype and release the prototypeBeanExpensive resources occupied. In order to letSpringContainer release prototype scopebeanPlease try to use custombeanThe post processor contains thebeanThe reference resource can be released through the post processor.

in some ways,SpringThe container is within the scope of the prototypebeanThe role isJava newOperator. All lifecycle management beyond this point must be handled by the client. (more aboutSpringIn containerbeanLifecycles, viewing lifecycle callbacks)

1.5.3 dependency between singleton and prototype beans

When you use dependency prototypesbeanSingleton scope ofbeanThe prototype is referenced by a single instancebean)It should be noted that these dependencies are resolved at initialization time. So if you rely on injecting a prototypebeanTo a singletonbeanA new prototypebeanIs initialized and dependency injected into a singletonbean。 The prototype instance is the only one provided to the singleton scopebeanAn example of. (Note: when a single instance references a prototype bean, there will be only one prototype bean)

However, suppose you want singleton scopebeanGet prototype scope repeatedly at run timebeanA new instance of. You can’t rely on injecting a prototypebeanTo a singletonbeanBecause the injection occurs only once, whenSpringContainer instantiation singletonbean, parsing and injecting its dependencies. If you need a prototype more than once at run timebeanView method injection

1.5.4 Request, Session, Application, and WebSocket Scopes

requestsessionapplication, andwebsocketScope is only used by youSpringOfApplicationContextImplementation (for example:XmlWebApplicationContext)Is valid. If you combine these scopes with the regularSpring IoCContainer (e.gClassPathXmlApplicationContext)When used together, aIllegalStateExceptionThe unknown exception is thrownbeanScope.

  • Initialize web configuration

    To support the scope of these beans inrequestsessionapplication, andwebsocketLevel (WEB scope bean). Some minor initialization configuration is required before you define your bean. (this initialization installation is not required for standard scopes:singletonprototype)。

    This specific initialization depends on how you complete the installationServletEnvironmental Science.

    IfSpring Web MVCAccess scope inbeanIn fact, theSpring DispatcherServletNo special settings are required in the request to be processed.DispatcherServletAll relevant States have been exposed.

    If you useServlet 2.5 WebContainer, request processing inSpringOfDispatcherServletExternal (e.g. when usingJSForStructs)You need to registerorg.springframework.web.context.request.RequestContextListenerServletRequestListener。 aboutServlet 3.0+This can be done by using theWebApplicationInitializerThe interface is programmed. Or, for old containers, add the following statement to yourwebapplication programweb.xmlDocument:

    <web-app>
        ...
        <listener>
            <listener-class>
                org.springframework.web.context.request.RequestContextListener
            </listener-class>
        </listener>
        ...
    </web-app>

    Or, if you have problems with your listener settings, consider usingSpringOfRequestContextFilter。 Filter mapping depends on the surroundingWebApplication configuration. So you have to change it appropriately. The following list showswebapplication programfilterPart of the configuration:

    <web-app>
        ...
        <filter>
            <filter-name>requestContextFilter</filter-name>
            <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>requestContextFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        ...
    </web-app>

    DispatcherServletRequestContextListenerand

    RequestContextFilterIt’s the same thing that’s going to happenHTTPThe request object is bound to the thread that serves the request. This makesrequestandsessionThe scope bean is available further down the call chain.

  • RequestScope

    Consider the following XML aboutbeanDefinition of:

    <! -- request scope is request -- >

    SpringContainer by usingLoginActionBean is defined as eachHTTPCreate aLoginActionNew instance bean. in other words,loginActionThe scope of the bean isHTTPRequest level. You can change the internal state of the created instance as needed. Because from the sameloginActionOther instances created by the bean definition do not see these changes in state. When the request is processed, the scope of the bean changes fromrequestdiscard. (Note:scope="request"Each request is thread level isolated and does not interfere with each other)

    When using annotations to drive components orJava ConfigWhen,@RequestScopeAnnotations can assign a component to arequestScope. The following example shows how to use:

    @Requestscope / / specify the scope access as request
  • Session scope

    Consider the followingbeanDefinedXMLto configure:

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

    SpringContainer by usinguserPreferencesThe bean of is defined as a singleHTTP SessionCreate aUserPreferencesA new instance of. let me put it another way,userPreferencesBeans work effectively at the HTTP session level. Like request scoped beans, you can change the internal state of the created instance as needed, knowing that others are also using the same`userPreferencesThe HTTP session instance of the instance created by the bean definition also does not see these state changes because they are specific to a single HTTP session. WhenHTTPWhen the session is eventually discarded, theHTTPConversationalbeanIt will also be discarded.

    When using annotations to drive components orJava ConfigWhen,@SessionScopeAnnotations can assign a component to asessionScope. The following example shows how to use:

    @SessionScope
    @Component
    public class UserPreferences {
        // ...
    }
  • Application scope

    Consider the following XML aboutbeanDefinition of:

    <bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>

    SpringContainer by usingappPreferencesIs defined as theWebApplication creates aAppPreferencesA new instance of the bean. in other words,appPreferencesThe scope ofServletContextAnd as a regularServletContextProperty is stored. This andSpringThe singleton bean for is similar, but with two important differences: eachServletContextIt’s a singleton, not eachSpringOfApplicationContext(in the givenWebThere may be more than one in the application), and it is actually exposed, so as aServletContextProperty is visible.

    When using annotations to drive components orJava ConfigWhen,@ApplicationScopeAnnotations can assign a component to aapplicationScope. The following example shows how to use:

    @ApplicationScope
    @Component
    public class AppPreferences {
        // ...
    }
  • Scope bean as dependency

    The spring IOC container not only manages the instantiation of objects (beans), but also the connections of collaborators (or dependencies). For example, if you want to inject an HTTP request scoped bean into another bean with a longer scope, you can choose to inject an AOP proxy instead of a bean with a defined scope. That is, you need to inject a proxy object that exposes the same public interface as the scope object, but you can also retrieve the actual target object from the relevant scope (such as HTTP request) and delegate the method call to the actual object.

    Here it isbeanThe scope is between singletons that you can use<aop:scoped-proxy/>。 Then, through a serializable intermediate proxy reference, the target singleton can be retrieved during deserializationbean

    When stated<aop:scoped-proxy/>Prototype scopebeanEach method call to the shared proxy causes a new target instance to be created and the call is then forwarded to that target instance.

    Similarly, scope proxies are not accessed from shorter scopes in a lifecycle safe mannerbeanThe only way. You can also declare your injection point (i.e., constructor orSetterParameter or auto injection field) for example:ObjectFactory<MyTargetBean>, allowedgetObject()Call to retrieve the current instance on demand every time it is needed – no instances are kept or stored separately.

    As an extension variant, you can declareObjectProvider<MyTargetBean>Provides additional ways to obtain, includinggetIfAvailableandgetIfUnique

    This variant of jsr-330 is calledProviderAnd withProvider <MyTargetBean>Statement and corresponding to each retrieval attemptget()Call. For more details on the overall jsr-330, see here.

    In the following example, only one line of configuration is required, but it is important to understand the reasons behind it:

    <?xml version="1.0" encoding="UTF-8"?>
    1. This line defines the agent.

Create a proxy by inserting a child<aop:scoped-proxy/>Element to a scopebeanDefinition (see select proxy type to create and schema based XML configuration). Why are thesebeanIs defined inrequestsessionAnd custom scopes are required<aop:scoped-proxy/>Elements? Consider the following singletonbeanDefine and compare it to what needs to be defined for the above scope (note, belowuserPreferencesIncomplete bean definition)

<! -- No< aop:scoped-proxy/ >Elements -- >

In the previous example, the singleton bean(userManager)Is injected with a reference toHTTP SessionScopedbean (userPreferences)。 The salient point is thatuserManagerBean is a singleton bean: this instance is initialized once per container value, and its dependencies (in this case, there is only one,userPreferencesBean) is injected only once. This means thatuserManagerBeans run only in the sameuserPreferencesThat’s the initial injection.

When injecting a short life cycle scopebeanTo a long lifecycle scopebeanThis is not the way we expect (e.g. injecting an HTTPSessionScope collaboratorsbeanAs a dependency injection into the singletonbean)。 Instead, you only need oneuserManagerObject, and in theHTTPYou need an HTTP session specificuserPreferencesObject. Therefore, the container creates an object that exposes theUserPreferencesClasses are identical public interfaces (ideally, objects areUserPreferencesInstance) from the scope mechanism (HTTP request,SessionAnd so on) to get the realUserPreferencesObject. The container injects the proxy object into theuserManagerBean, which doesn’t know thisUserPreferencesThe reference is a proxy. In this case, whenUserManagerInstance call in dependency injectionUserPreferencesObject, it actually calls the method on the proxy. Then the proxy from (in this case)HTTPGet the actualUserPreferencesObject and delegate the method call to the retrieved actualUserPreferencesObject.

Therefore, in therequest-scopedandsession-scopedYou need the following (correct and complete) configuration to inject the bean into the collaboration object, as shown in the following example:

<bean id="userPreferences" class="com.something.UserPreferences" scope="session">
    <aop:scoped-proxy/>
  </bean>
<bean id="userManager" class="com.something.UserManager">
      <property name="userPreferences" ref="userPreferences"/>
  </bean>
  • Agent type selection

    By default, whenSpringThe container isbeanCreate a proxy, thisbeanadopt<aop:scoped-proxy/>Element is marked based onCGLIBThe class proxy for is created.

    CGLIBProxy interceptor only public methods are called! Do not call non-public methods on the proxy.

    Or, you can create a scope forbeanto configureSpringContainer creation standardJDKInterface based proxy by specifying<aop:scoped-proxy/>Elementalproxy-target-classProperty value isfalse。 Using JDK based proxies means that you don’t need other libraries in the application classpath to affect such proxies. But it also means scopeBeanMust implement at least one interface and be scopedBeanAll collaborators injected into it must reference this through one of their interfacesBean。 The following example shows an interface based proxy:

    <!-- DefaultUserPreferences implements the UserPreferences interface -->

    More details about choosing based onclassOr based on the interface proxy, refer to the proxy mechanism

    Reference code:com.liyong.ioccontainer.starter.XmlBeanScopeIocContainer

1.5.5 custom scope

beanThe scope mechanism is extensible. You can define your own scopes or even redefine existing scopes, although the latter is considered bad practice, you cannot override built-in singletons and prototype scopes.

  • Create a custom scope

    To integrate your custom scopes intoSpringContainer, you need to implementorg.springframework.beans.factory.config.ScopeInterface, described in this chapter. For ideas on how to implement your own scope, seeScopeImplementation provides information aboutSpringFramework itself andScopeWhich details the method you need to implement.

    ScopeInterface has four methods to get objects from the scope, remove them from the scope, and have them destroyed.

    For example:SessonOfscopeImplement returnSeasonScopebean(if it doesn’t exist, this method returns a new onebeanInstance, which is bound to the session for future reference). The following method returns the object from the underlying scope:

    Object get(String name, ObjectFactory<?> objectFactory)

    For example:SessionOfscopeRemove the season scopebeanFrom the bottomSession。 Object should be returned, but if the name specified by the object does not exist, you can return itnull。 The following method removes the object from the underlying scope:

    Object remove(String name)

    The following methods register the callbacks that should be executed when destroying the scope or the specified object in the scope:

    void registerDestructionCallback(String name, Runnable destructionCallback)

    Check Javadoc orSpringScope implements information about more destruction callbacks.

    The following method gets the session identifier of the underlying scope:

    String getConversationId()

    This means that each scope is different. aboutSessionImplementation of the scope, which can beSessionIdentifier.

  • Using custom scopes

    Before you write and test one or more customizationsScopeYou need to make it happenSpringThe container knows your new scope. The following methods areSpringMain methods to register new scopes in containers:

    void registerScope(String scopeName, Scope scope);

    This method is used inConfigurableBeanFactoryIs defined on the interface, which can be accessed through theSpringMost of the specificApplicationContextImplementationBeanFactoryProperty.

    registerScope(..)The first parameter of the method is the unique name about the scope.SpringExamples of such names in the container itself include singletons and prototypes.registerScope(..)The second parameter of the method is customScoperealization

    Suppose you write your customScopeImplement and register it as in the example below.

    The following example usesSimpleThreadScopeIt includesSpringBut it is not registered by default. It’s the same for your own custom scope implementation.

    Scope threadScope = new SimpleThreadScope();

    You can then create bean definitions according to the scope rules of your custom scope, as follows:

    <bean id="..." class="..." scope="thread">

    By customizingScopeImplementation, you are not limited to registering scopes programmatically. You can register scope declaratively by using theCustomScopeConfigurer, similar to the following example:

    <?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:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
            <property name="scopes">
                <map>
                    <entry key="thread">
                        <bean class="org.springframework.context.support.SimpleThreadScope"/>
                    </entry>
                </map>
            </property>
        </bean>
    
        <bean id="thing2" class="x.y.Thing2" scope="thread">
            <property name="name" value="Rick"/>
            <aop:scoped-proxy/>
        </bean>
    
        <bean id="thing1" class="x.y.Thing1">
            <property name="thing2" ref="thing2"/>
        </bean>
    
    </beans>

    When inFactoryBeanConfiguration in implementation<aop:scoped-proxy/>The factory is scopedbeanItself, not fromgetObject()Returns the object.

    Reference code:com.liyong.ioccontainer.starter.XmlCustomScopeIocContainer

author

Personally engaged in the financial industry, I have worked in Chongqing’s first-class technical team, such as yijifu, Sijian technology, a car Hailing platform, etc. at present, I am in charge of the construction of unified payment system in a bank. I have a strong interest in the financial industry. At the same time, it also practices big data, data storage, automatic integration and deployment, distributed microservices, responsive programming, artificial intelligence and other fields. At the same time, it is also keen to share technology and create official account and blog site.

Blog address: http://youngitman.tech

CSDN: https://blog.csdn.net/liyong1…

The official account of WeChat:

Spring 5 Chinese parsing core - bean scope of IOC container

Technical exchange group:

Spring 5 Chinese parsing core - bean scope of IOC container

Recommended Today

Summary of recent use of gin

Recently, a new project is developed by using gin. Some problems are encountered in the process. To sum up, as a note, I hope it can help you. Cross domain problems Middleware: func Cors() gin.HandlerFunc { return func(c *gin.Context) { //Here you can use * or the domain name you specify c.Header(“Access-Control-Allow-Origin”, “*”) //Allow header […]