The little Thing before MVC series (4): Httppipeline detailed analysis (i)
Article content
Continue with the contents of the previous chapter, get the instance through HttpApplicationFactory's getapplicationinstance static method, and then execute the BeginProcessRequest method of the instance to perform the remaining HTTP Pipeline operation, the code is as follows:
IHttpHandler app = httpapplicationfactory.getapplicationinstance (context);
So what exactly did getapplicationinstance do with this method? Is it just a new object? It should not feel like, so let's take a look at the HttpApplicationFactory class of getapplicationinstance static method source code:
Internal StaticIHttpHandler GetApplicationInstance (HttpContext context) {if(_customapplication! =NULL) return_customapplication; //Check to see if it ' s a debug Auto-attach request if(context. Request.isdebuggingrequest)return NewHttpdebughandler (); _theapplicationfactory.ensureinited (); _theapplicationfactory.ensureappstartcalled (context); return _theapplicationfactory.getnormalapplicationinstance (context); }
There are 3 lines of code that I've marked as bold, and before explaining the specifics of each line of code, let's look at where the _theapplicationfactory object instance came from and see it as a singleton implementation by looking at the declaration code for that field.
// The only instance of application factory Private Static New HttpApplicationFactory ();
The first line of bold code is the Ensureinited method that executes the instance, and this method calls the Init method by means of lock (the benefit is naturally needless to say), the code is as follows:
Private void ensureinited () { if (! _inited) { lock (this) { if (! _inited) { Init (); true ; } } }}
By finding the code for the Init method and the details in the following 2 lines of code, we can tell that the 2 lines of code are basically getting the content from Global.asax and compiling it.
_appfilename = getapplicationfile (); CompileApplication ();
So, the Httpapplicationfactory._theapplicationfactory.ensureinited () method first checks whether the httpapplicationfactory is initialized, if not, is initialized by Httpapplicationfactory.init (). In Init (), get the full path to the Global.asax file first, and then call CompileApplication () to compile the global.asax.
The ensureappstartcalled method of the bold in line 2nd will eventually call the following private method Fireapplicationonstart, the code is as follows:
private void Fireapplicationonstart (HttpContext context) { (_onstartmethod! = null = Getspecialapplicationinstance (); App. Processspecialrequest (context, _onstartmethod, _onstartparamcount, this Eventargs.empty, null ); Recyclespecialapplicationinstance (APP); }}
Through the code we can learn that httpapplicationfactory._theapplicationfactory.ensureappstartcalled creates a specific HttpApplication instance, Triggers the Applicationonstart event, executing the Application_Start (object sender, EventArgs e) method in Asp.global_asax. It is then recycled as soon as the event is processed, because the system initialization takes only one time, but the getspecialapplicationinstance in it will do something special for IIS7, as we'll see in the chapters that follow.
The bold code on line 3rd is what we're going to say here, and the code in the method is as follows:
PrivateHttpApplication Getnormalapplicationinstance (HttpContext context) {HttpApplication app=NULL; Lock(_freelist) {if(_numfreeappinstances >0) {app=(HttpApplication) _freelist.pop (); _numfreeappinstances--; if(_numfreeappinstances <_minfreeappinstances) {_minfreeappinstances=_numfreeappinstances; } } } if(App = =NULL) { //If ran out of instances, create a new oneApp =(HttpApplication) httpruntime.createnonpublicinstance (_theapplicationtype); using(NewApplicationimpersonationcontext ()) {app. Initinternal (context, _state, _eventhandlermethods); } } returnapp;}
If there is an idle HttpApplication instance, it is used directly, if no new creation is made, then the Initinternal method is called to initialize the related content, and the HttpApplication instance is finally returned.
Let's take a look at the core method of HttpApplication Initinternal is doing something, first on the code, a bit more, but it is worth it:
Internal voidInitinternal (HttpContext context, HttpApplicationState State, methodinfo[] handlers) {Debug.Assert (context!=NULL,"context! = NULL"); //Remember State_state =State ; Perfcounters.incrementcounter (Appperfcounter.pipelines); Try { Try { //Remember context for config lookups_initcontext =context; _initcontext.applicationinstance= This; //Set config path to is application path for the application initializationContext. Configurationpath =context. Request.applicationpathobject; //Keep HttpContext.Current working while running user code using(NewDisposablehttpcontextwrapper (context)) { //Build Module list from config if(httpruntime.useintegratedpipeline) {Debug.Assert (_moduleconfiginfo!=NULL,"_moduleconfiginfo! = null"); Debug.Assert (_moduleconfiginfo.count>=0,"_moduleconfiginfo.count >= 0"); Try{context. Hiderequestresponse=true; _hiderequestresponse=true; initintegratedmodules (); } finally{context. Hiderequestresponse=false; _hiderequestresponse=false; } } Else{ initmodules (); //This is used exclusively for Integrated modeDebug.Assert (NULL= = _modulecontainers,"NULL = = _modulecontainers"); } //hookup event handlers via reflection if(Handlers! =NULL) hookupeventhandlersforapplicationandmodules (handlers); //initialization of the derived class_context =context; if(Httpruntime.useintegratedpipeline && _context! =NULL) {_context. Hiderequestresponse=true; } _hiderequestresponse=true; Try{Init (); } Catch(Exception e) {recorderror (e); } } if(Httpruntime.useintegratedpipeline && _context! =NULL) {_context. Hiderequestresponse=false; } _hiderequestresponse=false; _context=NULL; _resumestepswaitcallback=NewWaitCallback ( This. Resumestepswaitcallback); //Construct The execution steps array if (httpruntime.useintegratedpipeline) {_stepmanager = new Pipelinestepman Ager (this); } Else {_stepmanager = new applicationstepmanager (this ); } _stepmanager.buildsteps (_resumestepswaitcallback); } finally{_initinternalcompleted=true; //Reset Config pathContext. Configurationpath =NULL; //don ' t hold in to the context_initcontext.applicationinstance =NULL; _initcontext=NULL; } } Catch{//Protect against exception filters Throw; }}
The code mainly has 2 functions, one is to initialize the familiar httpmodules, one is to execute over 20 life cycle event processing function through Buildsteps (this part, we will explain in detail the HTTP Pipeline in the next section). From the above code we can see that each function has a special judgment, determine whether IIS is IIS7 Integrated mode, if there is a special step, if not just go the general steps, The direct differences between the two are: IIS7 initialization httpmodules will be read from the Site configuration modules (because IIS7 preloaded CLR and mass modules), Buildsteps, IIS7 Integrated mode is your own special process (loading the httpmodules on the server).
Let's sum up and look at the code, the main functions of the Initinternal method are as follows:
- Initmodules (): loads the corresponding httpmodules according to the settings of the Web. config.
- Initintegratedmodules (): Httpmoduels under System.webserver in Httpmoduels and Web. config in IIS7 Integrated mode is loaded in the server settings.
- Hookupeventhandlersforappplicationandmodules: invokes the corresponding event handler in the HttpApplication instance, based on the event that occurred.
- Create many instances of classes that implement the IExecutionStep interface and add them to the _execsteps of the current HttpApplication instance, waiting for callbacks to execute. From here we can see that HttpApplication is processing the request asynchronously, and much of the processing of the request is placed in the _execstep waiting for the callback to execute.
At this point, except for more than 20 cycle events and handler-related code we did not explain, and other HttpApplication-related and helpful, it is almost clear. For more than 20 cycles of events and the execution of handler, we'll explain in more detail in the next section.
References:
Http://msdn.microsoft.com/en-us/magazine/cc188942.aspx
Http://msdn.microsoft.com/en-us/library/bb470252.aspx
Http://www.cnblogs.com/zhaoyang/archive/2011/11/16/2251200.html
Synchronization and recommendations
This article has been synchronized to the directory index: Thelittle Thing before MVC series
MVC before the point of the series of articles, including the original, translation, reprint and other types of articles, if it is useful to you, please recommend supporting a, to the power of the uncle writing.
Original link This article by Bean John Blog Backup expert remote One click release
The little Thing before MVC series (4): Httppipeline detailed Analysis (i) (reproduced)