Inject the request member domain into the SPRINGMVC controller _spring

Source: Internet
Author: User
Tags prepare

Https://www.cnblogs.com/abcwt112/p/7777258.html


Theme

1 problems encountered in the work .... We have defined a controller base class, and all SPRINGMVC custom controller inherit it .... Define a @autowired httpservletrequest request within it; Can you take requestparamters and attributes from this object? Will there be any effect between multithreading?

Thinking

First thought, I think this should not be. Why?

The injection bean is when the spring container starts ... the implementation class for the request is in Tomcat (the servlet container I use is tomcat) .... I didn't configure this bean in spring's container. The injection should be a failure ...

A step back, even if it is successful .... That's 1 objects injected. Each time the servlet receives a request, it regenerates 1 requests ... It's obviously different from the one you started with .... It's impossible to be successful ...

If that's true .... Then there's no such article .... Then practiced a bit. It is possible to find this injection. There is no problem with using it to get data ....

In fact, I had a look at that time debug, basically know why can be taken to the data. But I don't know the principle and spring (SPRINGMVC) process ... So now look at it and write it down ...

Principle

First, let's take a look at the distinction between injecting request as a parameter in the method and injecting the request into the member domain ....

The member domain is injected with 1 proxy objects. is an instance of Autowireutils.objectfactorydelegatinginvocationhandler.

method is to inject the Requestfacade object of the general Tomcat native.

So this is different ...

 1/** 2 * Reflective invocationhandler for lazy access to the current target object. 3/4 @SuppressWarnings ("Serial") 5 private static class Objectfactorydelegatinginvocationhandler Implemen
 TS Invocationhandler, Serializable {6 7 private final objectfactory<?> objectfactory; 8 9 public Objectfactorydelegatinginvocationhandler (objectfactory<?> objectfactory) {A.
Objectfactory = objectfactory; @Override public Object Invoke (object proxy, Method method, object[] args) throws T                 hrowable {String methodname = Method.getname (); if (Methodname.equals ("equals")) {17
Only consider equal when proxies are identical.
return (proxy = = Args[0]);                 /Else if (methodname.equals ("Hashcode")) {//Use hashcode of proxy. 22 Return System.identityhashcode (prOxy); ' Else If ' (Methodname.equals ("toString")) {= return This.objectFactory.toS
Tring ();             The try {return Method.invoke (This.objectFactory.getObject (), args) 29             catch (InvocationTargetException ex) {throw ex.gettargetexception (); 32 } 33} 34}

When most of the methods of the proxy object (that is, member domain request) are invoked, Objectfactorydelegatinginvocationhandler uses Objectfactory to get the object (native request), The method on the object is called again.

Then let's take a look at the steps that the Xmlwebapplicationcontext initializes to the request into the controller that has an impact on the injection request member domain.

Refresh method and Postprocessbeanfactory method

ApplicationContext's Abstract implementation class Abstractapplicationcontext (basically all AC's parent classes) defines the AC Refresh method (which includes the process of using beanfactory injection beans).

 1 @Override 2 public void Refresh () throws Beansexception, IllegalStateException {3 synchronized (This.sta
 Rtupshutdownmonitor) {4//Prepare this context for refreshing.
 5//Record start WAC start initialization time, set activation tag, servlet related param set to env (previously done 1 times), verify the Env in the necessary props 6 preparerefresh ();
 7 8//Tell the subclass to refresh the internal bean factory. 9//The old BF in the Bean deleted, new 1 BF, set some properties, load XML configuration file configurablelistablebeanfactory Beanfactory = Obtain
Freshbeanfactory ();
One//Prepare The Bean Factory for use in this context. 13//1. Set the BF parsing bean configuration Some objects that need to be used, such as Env. 2. Register some beanpostprocessor such as applicationcontextawareprocessor to set aware required object 14//3. Ignores some specific class injected objects and sets some specific class injected
The object is a specified value of 15//4. The properties map in some env is registered as a bean to the Bf preparebeanfactory (beanfactory); A try {//allows post-processing of the Bean factory in context SubclasSes. 20//1. Set up a beanpostprocess for Servletcontextaware implementation class to inject servlet related objects 21//2. Add Requetsscop in BF E, etc. scope 22//3. Register Servletcontext,config,servletinitparams,servletattribute as a bean to the BF p
Ostprocessbeanfactory (beanfactory);
Factory//Invoke the processors registered as beans in the context.
26//initialization and invocation of Beanfactorypostprocessor invokebeanfactorypostprocessors (beanfactory);
The/Register bean processors that intercept bean creation.
30//Registered Beanpostprocessors and registered to the Bf registerbeanpostprocessors (beanfactory);
The//Initialize message source is for the context.
Initmessagesource ();
//Initialize Event Multicaster for the this context.
Panax Notoginseng initapplicationeventmulticaster (); Special//Initialize other beans on specific context subClasses.
Onrefresh ();
A/Check for listener beans and register them.
Registerlisteners ();
Instantiate all remaining (Non-lazy-init) singletons.
Finishbeanfactoryinitialization (beanfactory);
Step:publish//Last corresponding event.
Finishrefresh (); (Beansexception ex) {Wuyi Logger.warn ("Exception encountered during context Initiali
Zation-cancelling refresh attempt ", ex);
Already//Destroy created singletons to avoid dangling.
Destroybeans ();
Flag/Reset ' active '.
CancelRefresh (ex);
Propagate//exception to caller.
Throw ex; 61} 62} 63}

There are 1 template methods

Postprocessbeanfactory (beanfactory);

This method allows abstractapplicationcontext subclasses to overwrite it and implement a custom for the BF (this time the bean's defination path has been specified, but the bean has not yet loaded).

Abstractrefreshablewebapplicationcontext covered this method.

 1/** 2 * Register request/session scopes, a {@link servletcontextawareprocessor}, etc. 3 * 1. Set up a beanpostprocess for Servletcontextaware implementation class to inject servlet-related objects 4 * 2. In the BF, add Requetsscope etc. scope 5 * 3. Put serv Letcontext,config,servletinitparams,servletattribute as Bean registered to BF 6 * 7 * 8 @Override 9 protected VO ID postprocessbeanfactory (configurablelistablebeanfactory beanfactory) {10//Set a beanpostprocess to Servletcontexta Ware implementation classes inject servlet-related objects One beanfactory.addbeanpostprocessor (new Servletcontextawareprocessor (this.servletcontext, th
Is.servletconfig));
Beanfactory.ignoredependencyinterface (Servletcontextaware.class);
Beanfactory.ignoredependencyinterface (Servletconfigaware.class);  14 15//in BF add Requetsscope etc scope webapplicationcontextutils.registerwebapplicationscopes (beanfactory,
This.servletcontext);        17///Servletcontext,config,servletinitparams,servletattribute as Bean Register to BF 18 Webapplicationcontextutils.registerenvironmentbeans (Beanfactory, This.servletcontext, this.servletConfig); 19}

One of them is a step

Webapplicationcontextutils.registerwebapplicationscopes (Beanfactory, This.servletcontext);

Here are some special bean scope settings, such as Request,session,globalsession,application. (This is not the subject of my article, of course.)

Some special autowired beans are set at the same time

Beanfactory.registerresolvabledependency (Servletrequest.class, New Requestobjectfactory ());
Beanfactory.registerresolvabledependency (Servletresponse.class, New Responseobjectfactory ());
Beanfactory.registerresolvabledependency (Httpsession.class, New Sessionobjectfactory ());
Beanfactory.registerresolvabledependency (Webrequest.class, New Webrequestobjectfactory ());

ServletRequest implementation classes (such as HttpServletRequest) are specified to use requestobjectfactory injection.

Requestobjectfactory

Requestobjectfactory is a objectfactory is the objectfactory in front of the objectfactorydelegatinginvocationhandler. So calling a method on a member domain request object is actually Gets the object by Requestobjectfactory and then calls the method.

1     /**
 2      * Factory that exposes, the current request object, on demand.
 3
 /4     @SuppressWarnings ("Serial")
 5     private static class Requestobjectfactory implements Objectfactory<servletrequest>, Serializable {
 6 
 7         @Override 8 public         ServletRequest GetObject () {
 9 return             currentrequestattributes (). Getrequest ();
One
@Override public         String toString () {             HttpServletRequest ";
}     

1     /** 2 * Return to the current      requestattributes instance as servletrequestattributes.
 3      *
 4      * @see requestcontextholder#currentrequestattributes ()
 5 */
 6     private static Servletrequestattributes currentrequestattributes () {
 7         requestattributes requestattr = Requestcontextholder.currentrequestattributes ();
 8         if (!) ( Requestattr instanceof Servletrequestattributes)) {
 9             throw new IllegalStateException ("The current request is Not a servlet request ");
All         return         (servletrequestattributes) requestattr;
The     }

The GetObject method for Requestobjectfactory is simply to invoke the static method

Requestcontextholder.currentrequestattributes (). Getrequest ()

Requestcontextholder

 1 public static Requestattributes Currentrequestattributes () throws IllegalStateException {2 Requestattribu
 TES attributes = Getrequestattributes (); 3 if (attributes = = null) {4 if (jsfpresent) {5 attributes = Facesrequestattribute
 Sfactory.getfacesrequestattributes (); 6} 7 if (attributes = = null) {8 throw new IllegalStateException ("No Thread-bou nd request found: "+ 9" Are you referring to request attributes outside of a actual web request                         , "+" or processing a request outside of the originally receiving thread? "+ 11                         "If you are are actually operating within a Web request and still receive this message," + 12  "Your code is probably running outside of Dispatcherservlet/dispatcherportlet:" + "in" case, use Requestcontextlistener or Requestcontextfilter to ExpoSE the current request. ");
attributes return; 17}
1     /**
 2 * Return of the      Requestattributes currently bound to the thread.
 3      * @return The requestattributes currently bound to the thread,
 4      * or {@code null} if none bound
 5      * /
 6 public     static Requestattributes getrequestattributes () {
 7         requestattributes attributes = Requestattributesholder.get ();
 8         if (attributes = = null) {
 9             attributes = Inheritablerequestattributesholder.get ();
All         return         attributes;
The     }
1     private static final threadlocal<requestattributes> Requestattributesholder =
2             New Namedthreadlocal<requestattributes> ("Request attributes");
3 
4     private static final threadlocal<requestattributes> Inheritablerequestattributesholder =
5             new Namedinheritablethreadlocal<requestattributes> ("Request context");

There are some key methods.

So ultimately, the request is taken from the threadlocal ...

Frameworkservlet

So when was the request set to the threadlocal?

is operated in the parent class frameworkservlet of the Springmvc Dispatcherservlet.

1     /**
 2      * Delegate get requests to processrequest/doservice.
 3      * <p>will also is invoked by HttpServlet ' s default implementation of {@code Dohead},
 4      * with a {@code Nobodyresponse} that just captures the content length.
 5      * @see #doService
 6      * @see #doHead
 7      /
 8     @Override
 9     protected Final void Doget (HttpServletRequest request, httpservletresponse response)
throws             Servletexception, IOException {
One         processrequest (request, response);     /**      * Delegate POST requests to {@link #processRequest}.      * @see #doService
/@Override     protected final void DoPost ( HttpServletRequest request, HttpServletResponse response)             throws Servletexception, IOException {         ProcessRequest (request, response);     }

Whether you are doget or Dopost or Doxxx methods are commissioned ProcessRequest method to do.

 1/** 2 * Process this request, publishing a event regardless of the outcome.
 3 * <p>the actual event handling is performed by the abstract 4 * {@link #doService} template method.             5/6 protected final void ProcessRequest (HttpServletRequest request, httpservletresponse response) 7 Throws Servletexception, IOException {8 9 long starttime = System.currenttimemillis ();
e failurecause = null;
One localecontext Previouslocalecontext = Localecontextholder.getlocalecontext ();
Localecontext Localecontext = buildlocalecontext (request);
Requestattributes previousattributes = Requestcontextholder.getrequestattributes ();
Servletrequestattributes requestattributes = buildrequestattributes (Request, response, previousattributes);
Webasyncmanager Asyncmanager = Webasyncutils.getasyncmanager (request); Asyncmanager.registercallableinterceptor (FramewoRkServlet.class.getName (), New Requestbindinginterceptor ());
Initcontextholders (Request, Localecontext, requestattributes);              The try {doservice (Request, response), and catch (Servletexception ex) {27
Failurecause = ex;
Throw ex; The catch (IOException ex) {failurecause = ex; throw ex; 33} 3 4 catch (Throwable ex) {failurecause = ex; throw new Nestedservletexception ("Reques
T processing failed ", ex); Panax resetcontextholders (Request, Previouslocalecontext, Previousattribute
s);
if (requestattributes!= null) {requestattributes.requestcompleted (); 43} if (logger.isdebugenabled ()) {(Failurecause!= null) {The TH Is.logger.debug ("Could not complete requeSt ", Failurecause);                          M/Else {asyncmanager.isconcurrenthandlingstarted () {51
Logger.debug ("Leaving response open for concurrent processing"); This.logger.debug else {The successfully complete
D request "); The publishrequesthandledevent (Request, RESP
Onse, StartTime, Failurecause); 60} 61}

which calls the

Initcontextholders (Request, Localecontext, requestattributes);

1     private void Initcontextholders (
 2             httpservletrequest request, Localecontext Localecontext, Requestattributes requestattributes) {
 3 
 4         if (localecontext!= null) {
 5             Localecontextholder.setlocalecontext (Localecontext, this.threadcontextinheritable);
 6         }
 7         if (requestattributes!= null) {
 8             requestcontextholder.setrequestattributes ( Requestattributes, this.threadcontextinheritable);
 9         if (logger.istraceenabled ()) {One             logger.trace ("Bound request context to Thread:" + request);
}     

Is here set to the Requestcontextholder of the threadlocal ...

Summary

1. The request injected in controller is the JDK dynamic proxy object, instance of Objectfactorydelegatinginvocationhandler. When we call the member domain request method, we actually invoke the Objectfactory GetObject () Object. The objectfactory here is requestobjectfactory.

The GetObject of 2.RequestObjectFactory is actually taken from the threadlocal of Requestcontextholder.

3. The request has just entered the SPRINGMVC Dispatcherservlet will be set to the request related objects to Requestcontextholder threadlocal.

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.