"Spring" spring IOC principle and source code parsing scope=request, session

Source: Internet
Author: User

First, container 1. Container

Throws a point:beanfactory is an IOC container , and Applicationcontex is a spring container.

What is a container? Collection and container These two words have the meaning of storing what things, but placed in the world of the program ape, but is doomed to be very diverse. Collection, a set of objects that hold the Obj instanceof class as true, with a focus on storage ; Container, a container that can hold a wide variety of obj, but not just storage, he is called a container, More importantly, he is able to manage the life cycle and dependencies of the objects being stored.

containers: For storing objects and for lifecycle management and dependency management of the objects being stored.

2. Spring IOC container is beanfactory

The Spring IOC container is a beanfactory, and it is based on the "container" argument.

Before the analysis of logic and source code, do some groundwork. For program apes using spring, commonly used are applicationcontext interfaces and their implementation subclasses, Claspathxmlapplicationcontext, Filesystemxmlapplicationcontext, Xmlwebapplicationcontext and Annotationconfigwebapplicationcontext, for these four classes, They all have a common abstract parent class Abstractrefreshableapplicationcontext, and it is in this abstract parent class that the beanfactory is decorated.

Public abstract class Abstractrefreshableapplicationcontext extends Abstractapplicationcontext {private Boolean allowbeandefinitionoverriding; Private Boolean allowcircularreferences; /** Bean Factory for this context */private defaultlistablebeanfactory beanfactory;

All use of the spring service through ApplicationContext access is using the Bean factory, and most importantly, the Bean factory implements all beanfactory interfaces, abstract classes, and full spring IOC logic.

Ii. Spring IOC Logic

  • Beanfactory is created when the spring container is initialized, and the Defaultlistablebeanfactory object is created by default;
  • The bean configuration information is loaded at the time the spring container is initialized and parsed into a beandefinition stored in the Defaultlistablebeanfactory Concurrenthashmap, either Singleton, Non-singleton beans are not created;
  • Beanfactory: Directly through the beanfactory to access the use of spring, whether the singleton, non-singleton beans are not created at the time of spring initialization, but at the time of the first Getbean is created, when the singleton bean is cached, Rather than singleton beans are not cached;
  • ApplicationContext: Directly through ApplicationContext to intervene with spring, Singleton and non-lazy-init beans are created and cached when spring is initialized, not singleton, The Lazy-init Bean is created at the first Getbean (the spring container initializes the Refresh method, the Finishbeanfactoryinitialization (Beanfactory) method is completed);
  • The dependency injection of all beans is done in the Getbean logic, of course, after the Getbean instantiation of the object;
  • For a bean with a request, session, and globalsession in a Web environment, the Requestcontextlistener listener listens for the creation and destruction of the request, thus managing the bean lifecycle. Specifically, the servletrequestattributes is bound to the current thread through threadlocal in Requestcontextholder, The Servletrequestattributes construction method is passed into the httpservletrequest for binding, and all beans are cached to the first time they are acquired Servletrequestattributes (because the request was passed in, actually finally deposited in the request's map container), and then directly from the servletrequestattributes is no longer created;

Third, source code Analysis 1. Creation of Beanfactory

The first section has already said that ApplicationContext commonly used four subclasses have a common abstract parent class Abstractrefreshableapplicationcontext, in which beanfactory are decorated, A more important point is that the parent class of Abstractrefreshableapplicationcontext is Abstractapplicationcontext, whose refresh method defines the process that the entire spring container starts.

That is, regardless of which applicationcontext you use to access the spring container, you will eventually enter the Abstractapplicationcontext Refresh method to complete the spring start.

Source analysis is based on the five-point logic presented in the spring IOC, found a very comprehensive article, so decided not to write, paste out share.

Spring: Source interpretation of spring IOC principles

As a part of the web that is not mentioned in the connection article, this article complements the principle and the source code analysis.

2. Web Scope (Request, session, Globalsession)

As mentioned in the inheritance relationship above, regardless of which applicationcontext, the end is to get the bean through Abstractbeanfactory.getbean (String), excerpt part of the code.

    @Override    public Object get (String name, objectfactory<?> objectfactory) {        = requestcontextholder.currentrequestattributes ();         = Attributes.getattribute (name, Getscope ());         if NULL ) {            = objectfactory.getobject ();            Attributes.setattribute (name, Scopedobject, Getscope ());        }         return scopedobject;    }

Get scope configuration content from beandefinition String scopeName = Mbd.getscope ();

This.scopes is a map<string, scope> for storing Scope object instances

Here, if it's request, get to Requestscope.

If it is session, get to sessionscope final scope scope = This.scopes.get (scopeName);

if (scope = = null) {throw new IllegalStateException ("No scope registered for scope '" + scopeName + "'");} try {//Here is the key//via Scope.get (String, objectfactory) access to the spring IOC container Object scopedinstance = Scope.get (beanname, new object Factory<object> () {@Override public Object getObject () throws Beansexception {beforeprototypecreation (beanname) ; try {return Createbean (Beanname, mbd, args);} finally {afterprototypecreation (beanname);}} }); Bean = getobjectforbeaninstance (scopedinstance, name, Beanname, mbd); } catch (IllegalStateException ex) {throw new Beancreationexception (Beanname, "Scope '" + ScopeName + "is not active fo R the current thread; "+" consider defining a scoped proxy for this bean if you intend to refer to it from a singleton ", ex);}

The class structure about scope is shown.

Abstractrequestattributescope defines the get (Beanname, Objectfactory) method, which accesses the spring IOC container, as shown in the source code.

Public Object Get (String name, objectfactory<?> objectfactory) {//Important here// Requestcontextholder the Requestattributes instance and the current thread are bound by threadlocal//requestattributes at the time of construction, you need to pass in HttpServletRequest, Later there will be source analysis and summary requestattributes attributes = Requestcontextholder.currentrequestattributes (); Gets the object from the current thread-bound requestattributes (actually a map from httpservletrequest)//If it has already been instantiated, it is no longer instantiated//otherwise enters the spring IOC procedure to get the object objects Scopedobject = Attributes.getattribute (name, Getscope ()); if (Scopedobject = = null) {Scopedobject = Objectfactory.getobject () attributes.setattribute (name, Scopedobject, Getscope ()); } return scopedobject; }

Now the question is Requestattributes, Requestcontextholder is a what ghost? Where do you come from?

To use spring web scope, to configure a listener Requestcontextlistener in XML, the answers to all the puzzles are here.

 Public classRequestcontextlistenerImplementsServletrequestlistener {Private Static FinalString Request_attributes_attribute =Requestcontextlistener.class. GetName () + ". Request_attributes "; @Override Public voidrequestinitialized (servletrequestevent requestevent) {if(! (Requestevent.getservletrequest ()instanceofhttpservletrequest)) {            Throw NewIllegalArgumentException ("Request is a httpservletrequest:" +requestevent.getservletrequest ()); } httpservletrequest Request=(HttpServletRequest) requestevent.getservletrequest (); Servletrequestattributes attributes=Newservletrequestattributes (Request);        Request.setattribute (Request_attributes_attribute, ATTRIBUTES);        Localecontextholder.setlocale (Request.getlocale ());    Requestcontextholder.setrequestattributes (attributes); } @Override Public voidrequestdestroyed (servletrequestevent requestevent) {servletrequestattributes attributes=NULL; Object reqattr=requestevent.getservletrequest (). getattribute (Request_attributes_attribute); if(reqattrinstanceofservletrequestattributes) {Attributes=(servletrequestattributes) reqattr; } requestattributes threadattributes=requestcontextholder.getrequestattributes (); if(Threadattributes! =NULL) {            //We ' re assumably within the original request thread ...Localecontextholder.resetlocalecontext ();            Requestcontextholder.resetrequestattributes (); if(Attributes = =NULL&& threadattributesinstanceofservletrequestattributes) {Attributes=(servletrequestattributes) threadattributes; }        }        if(Attributes! =NULL) {attributes.requestcompleted (); }    }}

This code requestcontextholder.setrequestattributes (attributes) is the key to combining spring web scope with the spring IOC.

Public abstract class Requestcontextholder {

Binds the servletrequestattributes to the current thread

private static final threadlocal<requestattributes> Requestattributesholder = new namedthreadlocal< Requestattributes> ("Request attributes");

private static final threadlocal<requestattributes> Inheritablerequestattributesholder = new Namedinheritablethreadlocal<requestattributes> ("Request context");

1 First step public static void Setrequestattributes (Requestattributes attributes) {setrequestattributes (attributes, False) ; }

2 second step, inheritable=false public static void Setrequestattributes (Requestattributes attributes, Boolean inheritable)

{if (attributes = = null) {resetrequestattributes ();}

else {

if (inheritable) {inheritablerequestattributesholder.set (attributes); Requestattributesholder.remove ();}

else {

3 The third step, bind the servletrequestattributes with the current thread requestattributesholder.set (attributes); Inheritablerequestattributesholder.remove (); }}}//Other source code, slightly}

At this point, the whole process is over. The session process is almost identical to the request, except that the life cycle is different and a lock is more. Summarize the content of the above source analysis.

Summary: All beans that are defined as request, session, globalsession by the spring Bean will not be actively initialized and will be instantiated and dependent injected when the spring IOC is getbean for the first time. However, when instantiating, you need to use Requestcontextholder (threadlocal mode) to bind the bean to the httpservletrequest in the current thread. and cached in the corresponding domain object (request or session) during the life cycle of the scope.

Finally, add a little, servletrequestattributes getattribute and setattribute. At the time of Getbean, The bean is first fetched from the Servletrequestattributes.getattribute, and if it is fetched, it is returned, otherwise the IOC is instantiated and called Servletrequestattributes.setarrtibute for caching, in fact Seta The Ttribute method is called Request.setattribute to complete.

public class Servletrequestattributes extends Abstractrequestattributes {

public static final String Destruction_callback_name_prefix = ServletRequestAttributes.class.getName () + ". Destruction_callback. ";

Private final httpservletrequest request; Private HttpServletResponse response;

private volatile HttpSession session;

Private final map<string, object> sessionattributestoupdate = new concurrenthashmap<string, Object> (1);

1 Servletrequestattributes object creation, you must have a HttpServletRequest instance

Public servletrequestattributes (HttpServletRequest request) {

Assert.notnull (Request, "request must not is null"); This.request = Request; }

Public Servletrequestattributes (HttpServletRequest request, httpservletresponse response) {This (request); This.response = response; }

Transpose Request.getattribute or Session.getattribute

Public Object getattribute (String name, int scope) {if (scope = = Scope_request) {if (!isrequestactive ()) {throw new IllegalStateException ("Cannot ask for request Attribute-request was not active anymore!"); } return This.request.getAttribute (name); } else {HttpSession session = GetSession (false); if (session! = null) {try {Object value =session.getattribute (name); F (value = null) {this.sessionAttributesToUpdate.put (name, value);} return value; } catch (IllegalStateException ex) {//Session invalidated-shouldn ' t usually happen.}} return null; } }

Transpose Reqeust.setattribute or session. SetAttribute public void SetAttribute (String name, Object value, int scope) {if (scope = = Scope_request) {if (!isrequest Active ()) {throw new IllegalStateException ("Cannot set request Attribute-request is not active anymore!");} this.requ Est.setattribute (name, value); } else {HttpSession session = GetSession (true); This.sessionAttributesToUpdate.remove (name); Session.setattribute ( name, value); } }

"Spring" spring IOC principle and source code parsing scope=request, session

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.