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

Source: Internet
Author: User

first, the container1. Containers

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 collection of objects that hold the Obj instanceof class as true, with emphasis on storage ; Container, containers, which can hold a wide variety of obj, But more than just storage, he is called a container, and more importantly he can 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, In order to manage the bean lifecycle, it is requestcontextholder to bind the servletrequestattributes to the current thread through threadlocal, 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 analysis1. Creation of Beanfactory

The first section has already said that ApplicationContext commonly used four subclasses have a common abstract parent class Abstractrefreshableapplicationcontext, To decorate the beanfactory in this class, a more important point is that the parent class of Abstractrefreshableapplicationcontext is Abstractapplicationcontext, Its Refresh method defines the process by which 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.

Get Scope configuration content from beandefinition String scopeName = Mbd.getscope ();//This.scopes is a map<string, scope> Used to hold a Scope object instance//here if it is request then get to requestscope//if it is session get to sessionscopefinal 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 Objectfactory<object> () {@Overridepublic 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 for th e 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, There will be source analysis and summary later 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.

Package Org.springframework.web.context.request;import Javax.servlet.servletrequestevent;import Javax.servlet.servletrequestlistener;import Javax.servlet.http.httpservletrequest;import Org.springframework.context.i18n.localecontextholder;public class Requestcontextlistener Implements Servletrequestlistener {private static final String Request_attributes_attribute = RequestContextListener.class.getName () + ". Request_attributes ";//When the request is created, the method is invoked to execute public void requestinitialized (Servletrequestevent requestevent) {// Only HTTP mode if (!) is supported Requestevent.getservletrequest () instanceof HttpServletRequest) {throw new IllegalArgumentException ("Request is not An httpservletrequest: "+ requestevent.getservletrequest ());} Get current Requesthttpservletrequest request = (HttpServletRequest) requestevent.getservletrequest ();// Create a Servletrequestattributes object//The object simply encapsulates the request, In fact, the beans that scope is request or session are stored in the request or session servletrequestattributes attributes = new Servletrequestattributes (request);//And REQuest Request.setattribute (Request_attributes_attribute, ATTRIBUTES); Localecontextholder.setlocale (Request.getlocale ());//Requestcontextholder encapsulates a threadlocal// So the meaning of this code is to bind servletrequestattributes with the current thread//because it is a static method, so that means wherever// Whenever you call Requestcontextholder.getrequestattributes (). getattribute (). SetAttribute () can bind beans and request And the object Requestcontextholder.setrequestattributes (attributes) is not duplicated during the life cycle of the request. When request is destroyed, the method call executes public void requestdestroyed (Servletrequestevent requestevent) {servletrequestattributes attributes = Null;object reqattr = Requestevent.getservletrequest (). getattribute (Request_attributes_attribute); if ( Reqattr instanceof servletrequestattributes) {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 && threadattributes instanceof servletrequestattributes) {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 servletrequestattributes to the current thread private static final ThreadLocal <RequestAttributes> requestattributesholder =new namedthreadlocal<requestattributes> ("Request Attributes ");p rivate static final threadlocal<requestattributes> Inheritablerequestattributesholder =new Namedinheritablethreadlocal<requestattributes> ("Request context");//1 The first step public static void Setrequestattributes (Requestattributes attributes) {setrequestattributes (attributes, false);} 2 second step, inheritable=falsepublic static void Setrequestattributes (Requestattributes attributes, Boolean inheritable) { if (attributes = = null) {resetrequestattributes ();} else {if (inheritable) {Inheritablerequestattributesholder.set ( attributes); Requestattributesholder.remove ();} else {//3 third step, bind the servletrequestattributes to the current thread requestattributesholder.set (attributes); Inheritablerequestattributesholder.remove ();}}} Other source, 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: Spring bean All the beans defined by scope as request, session, Globalsession will not be actively initialized and will be instantiated and dependent injected when first Getbean through the spring IOC. 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. In Getbean, the bean is fetched from the Servletrequestattributes.getattribute, and if it is fetched, it is instantiated by the IOC, and the Servletrequestattributes.setarrtibute is cached and is actually called Request.setattribute in the SetAttribute method.

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 The Servletrequestattributes object must be created with 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.getattributepublic Object getattribute (String name, int scope) {if (scope = = Scope_ REQUEST) {if (!isrequestactive ()) {throw new IllegalStateException ("Cannot ask for request Attribute-request are not ACTI Ve anymore! ");} return This.request.getAttribute (name);} else {HttpSession session = GetSession (false); if (session! = null) {try {Object value = Session.getattribute (name); if (Val UE = NULL) {this.sessionAttributesToUpdate.put (name, value);} return value;} catch (IllegalStateException ex) {//Session invalidated-shouldn ' t usually happen.}} return null;}} Transpose Reqeust.setattribute or session. setattributepublic void SetAttribute (String name, Object value, int scope) {if (scope = = Scope_request) {if (!isrequestact Ive ()) {throw new IllegalStateException ("Cannot set request Attribute-request is not active anymore!");} This.request.setAttribute (name, value);} else {HttpSession session = GetSession (true); This.sessionAttributesToUpdate.remove (name); Session.setattribute (name , value);}}

At this point, the analysis is over.

Note:

At first, I wanted to get the whole spring of the IOC logic out, but found that there were better articles written, so I decided not to write.

However, after reading that the IOC process in Web scope is not analyzed, so the second part of the article for Scope=reqeust, scope=session to implement the source code and the principle of the analysis process.

Finally, if there are mistakes in this article, please do not hesitate to correct, thank you!


Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

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