概要:
この記事は、ASP.NET 2.0 のソース コードに基づいて、ASP.NET 2.0 ランタイムの簡単な分析を行っています。ASP.NET 2.0 の要求処理プロセスとページ コンパイル モデルを理解するのに役立つことを願っています。
キーワード:
ASP.NET 2.0 ランタイム、原則、要求処理、ページ コンパイル、ASP.NET 2.0 HTTP ランタイムの
メイン クラス:
System.Web.HttpRuntime
System.Web.HttpApplicationFactory
System.Web.HttpApplication
System.Web.Compilation.BuildManager
System.Web.Compilation.ApplicationBuildProvider
System.Web.Compilation.BuildProvidersCompiler
System.Web.UI.PageHandlerFactory
リクエスト処理の簡単なフローチャート:
読書の提案:
読み取り中に ASP.NET 2.0 のソース コードを表示するには、Reflector ツールを使用します。
分析します:
ブラウザーを通じて ASP.NET 2.0 Web サイト上の asp.net ページへの要求を開始すると、IIS はまずサーバー側で要求を受け取り、それが asp.net ページであることを認識すると、非常に満足します。リクエストをそれによって処理する必要はなく、ASP.NET ISAPI に任せるだけです。 ASP.NET ISAPI の主なタスクは、aspnet_wp.exe が要求を処理できるように手配し、aspnet_wp.exe プロセスが疲れすぎてタスクを完了できない場合にその実行を監視することです。 ASP.NET ISAPI は彼を解雇し、新しい aspnet_wp.exe に置き換えて作業を担当させる予定です。
aspnet_wp.exe の主なタスクは、HTTP パイプラインと呼ばれる一連の管理オブジェクトに要求を渡すことです。 ASP.NET ISAPI をセールス マネージャーにたとえると、aspnet_wp.exe はプロダクション マネージャーであり、HTTP パイプラインはプロダクション パイプラインです。組立ラインを担当するチームは HttpRuntime です。生産マネージャー aspnet_wp.exe は、HttpRuntime チーム メンバーの ProcessRequest (HttpWorkerRequest wr) に注文を渡します。HttpRuntime は、最終的に ProcessRequestInternal (HttpWorkerRequest wr) によって組立ラインで生成されます。 ) 内部の分業に従っているため、ProcessRequestInternal(HttpWorkerRequest wr) が分析の焦点です。
ProcessRequestInternal の主な作業は次のとおりです。
1. HttpContext インスタンスを作成します。
2. 最初のリクエストを初期化します (EnsureFirstRequestInit)。
a) System.Web.HttpRuntime.FirstRequestInit を呼び出して、EnsureFirstRequestInit で初期化作業を実行します。たとえば、Web.Config 構成を RuntimeConfig に読み取り、bin ディレクトリからすべての dll ファイルをロードします。
3. HttpWriter インスタンスを作成します。
4. HttpApplicationFactory.GetApplicationInstance を呼び出して、HttpApplication インスタンスを作成します。
HttpApplicationFactory.GetApplicationInstance には 3 つの主要なメソッドがあります。
HttpApplicationFactory._theApplicationFactory.EnsureInited();
HttpApplicationFactory._theApplicationFactory.EnsureAppStartCalled(context);
HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(context);
これら 3 つのメソッドを 1 つずつ分析してみましょう。
1) HttpApplicationFactory._theApplicationFactory.EnsureInited();
このメソッドは、HttpApplicationFactory が初期化されているかどうかを確認します。初期化されていない場合は、HttpApplicationFactory.Init() によって初期化されます。
Init() では、まず global.asax ファイルのフル パスを取得し、次に CompileApplication() を呼び出して global.asax をコンパイルします。
コンパイルはどのように行われますか?
コンパイル作業は BuildManager によって完了します。 BuildManager は最初に GlobalAsaxType (つまり、HttpApplication) を取得し、次にコンパイルのために BuildManager.GetGlobalAsaxBuildResult() =》GetGlobalAsaxBuildResultInternal() =》EnsureTopLevelFilesCompiled() を呼び出します。
EnsureTopLevelFilesCompiled では、CompilationStage.TopLevelFiles が最初にコンパイルされ、次の 3 つのディレクトリ内のファイルがコンパイルされます。
a. CompileResourcesDirectory();
App_GlobalResources ディレクトリをコンパイルします。
b. CompileWebRefDirectory();
App_WebReferences ディレクトリをコンパイルします。
c. CompileCodeDirectories();
App_Code ディレクトリをコンパイルします。
次に、CompilationStage.GlobalAsax をコンパイルし、global.asax をコンパイルし、メソッド呼び出し: CompileGlobalAsax()=》ApplicationBuildProvider.GetGlobalAsaxBuildResult(BuildManager.IsPrecompiledApp)。
GetGlobalAsaxBuildResult の特定のコンパイルは、ApplicationBuildProvider と BuildProvidersCompiler によって完了します。
BuildProvidersCompiler.PerformBuild(); コンパイル作業を実行します。
ApplicationBuildProvider.GetBuildResult はコンパイルされた結果を取得します。
コンパイルが成功すると、App_global.asax.mlgx7n2v.dll に似た dll ファイルが、C:WINDOWSMicrosoft.NETFrameworkv2.0.50727Temporary ASP.NET Files の対応するディレクトリに生成されます。
コンパイルされたクラスは ASP.global_asax という名前で、HttpApplication から継承されます。
注: Web ディレクトリに Global.asax ファイルがない場合、App_global.asax.mlgx7n2v.dll などのファイルはコンパイルおよび生成されません。
2) HttpApplicationFactory._theApplicationFactory.EnsureAppStartCalled(コンテキスト);
特定の HttpApplication インスタンスを作成し、ApplicationOnStart イベントをトリガーし、ASP.global_asax の Application_Start(object sender, EventArgs e) メソッドを実行します。ここで作成された HttpApplication インスタンスは、イベントの処理後にリサイクルされます。
3) HttpApplicationFactory._theApplicationFactory.GetNormalApplicationInstance(コンテキスト);
このメソッドは、HttpApplication インスタンスを作成し、それを初期化します (System.Web.HttpApplication.InitInternal() メソッドを呼び出します)。
HttpApplication インスタンスの作成は、実際の _theApplicationType に基づいて行われます。 Web ディレクトリに global.asa ファイルがない場合、つまり、ASP.global_asax タイプを生成する動的コンパイルがない場合は、HttpApplication を直接インスタンス化します。 ASP.global_asax タイプが作成された場合は、ASP.global_asa をインスタンス化します。
HttpApplication インスタンスを作成した後、インスタンスの InitInternal メソッドを呼び出します。
InitInternal メソッドも注目するメソッドです。このメソッドの主な機能は次のとおりです。
1. InitModules(): Web.Config の設定に従って、対応する HttpModules を作成します。
2. HookupEventHandlersForAppplicationAndModules: 発生したイベントに基づいて、HttpApplication インスタンス内の対応するイベント処理関数を呼び出します。
3. IExecutionStep インターフェイスを実装するクラスのインスタンスを多数作成し、現在の HttpApplication インスタンスの _execSteps に追加して、コールバックの実行を待ちます。ここから、HttpApplication がリクエストを非同期で処理し、リクエストの多くの処理タスクが _execStep に置かれてコールバックが実行されるのを待機していることがわかります。
_execStep の主な処理作業は次のとおりです。
1) 要求されたパスのセキュリティ チェックを実行し、不正なパス アクセスを禁止します (ValidatePathExecutionStep)。
2) UrlMappings が設定されている場合は、RewritePath(UrlMappingsExecutionStep) を実行します。
3) BeginRequest、AuthenticateRequest などのイベント処理関数を実行します。
4) 現在のリクエストを処理する HttpHandler を取得します。ASP.NET ページのランタイム コンパイルもここで実行されます。 (MapHandlerExecutionStep)
この処理は、System.Web.HttpApplication.MapHttpHandler メソッドを呼び出すことで実行されます。
MapHttpHandlerでは、まずアクセスしたアドレスに応じて、web.configからIHttpHandlerFactoryを実装した対応する型を取得します。 asp.net ページの場合、デフォルトは PageHanlderFactory です。次に、PageHanlderFactory インスタンスを作成し、GetHandlerHelper を呼び出し、GetHandlerHelper で BuildManager.CreateInstanceFromVirtualPath を呼び出して、現在要求されている ASP.NET ページのインスタンスをコンパイルして作成します (コンパイルされている場合は、キャッシュから直接読み込みます)。
CreateInstanceFromVirtualPath は、いくつかのメソッド呼び出しの後、コンパイル タスクを BuildManager() に渡します。 CompileWebFile は、web.config から対応する BuildProvider を取得します。.aspx ファイルの場合、対応する BuildProvider は PageBuildProvider です。 PageBuildProvider がページをコンパイルする方法については、ここではこれ以上分析しません。興味がある場合は、ASP.NET 2.0 のソース コードをさらに調べてください。
5) 対応する HttpHandler の .ProcessRequest メソッドを呼び出してリクエストを処理します (非同期の場合は BeginProcessReques を呼び出します)。 (CallHandlerExecutionStep)
6) 応答内容を Filter に書き込みます。 (CallFilterExecutionStep)
5. HttpApplication インスタンスの BeginProcessRequest を呼び出して、リクエストを非同期に処理します。
前述の _execSteps で発生する処理の多くは、HttpRuntime が HttpApplication BeginProcessRequest を呼び出し、BeginProcessRequest で ResumeSteps を呼び出した後に実行されます。
ASP.NET 2.0 ランタイムは非常に複雑で理解しにくいが、ASP.NET 2.0 の重要な部分です。ASP.NET 2.0 ランタイム ソース コードを学ぶことは、ASP.NET 2.0 の原理についての理解をさらに深めるのに役立ちます。 ASP.NET 2.0 アプリケーションの開発には、多くの助けが必要です。この記事は、ASP.NET 2.0 ランタイムについて初めて学習したもので、ASP.NET 2.0 ランタイムをより深く理解するために書かれています。記事の内容についての批判や提案は歓迎です。
記事を書くことでライティングスキルが向上し、コミュニケーションが円滑になるだけでなく、記事を書くことで自分の考えが明確になり、深い思考が促進され、開発者はコーディングから少し離れて、テクノロジーへの理解を深められると感じています。技術的な記事を書くことは、自分自身を向上させるのに非常に役立ちます。