最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring.Net在MVC中實(shí)現(xiàn)注入的原理解析

 更新時(shí)間:2019年09月10日 08:23:25   作者:MedlarCanFly  
這篇文章主要介紹了Spring.Net在MVC中實(shí)現(xiàn)注入的原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

前言

本文將介紹Spring.Net(不僅僅是Spring.Net,其實(shí)所有的IoC容器要向控制器中進(jìn)行注入,原理都是差不多的)在MVC控制器中依賴注入的實(shí)現(xiàn)原理,本文并沒有關(guān)于在MVC使用Spring怎么配置,怎么使用,怎么實(shí)現(xiàn)。

引言放在前面,只是為了避免浪費(fèi)你的時(shí)間。

望你能靜心片刻,認(rèn)真閱讀。

情景

public class HomeController : Controller
  {
    //這是一個(gè)很神奇的注入
    private IBLL.IUserInfoService UserInfoService { get; set; }
    public ActionResult Index()
    {
      return Content(UserInfoService.GetName());
    }
  }

每次看代碼都有不一樣的理解,今天我在看MVC控制器中一個(gè)通過Spring.Net依賴注入的UserInfoService屬性時(shí),突然有些疑問,注入的前提是控制反轉(zhuǎn),這么說我的Controller是從IoC容器中來的了?但是我不記得在哪個(gè)地方有配置額,對(duì)此我展開了深入的研究。

從MVC本身開始

首先我們要搞懂MVC本身是通過什么方式獲取控制器對(duì)象的,本質(zhì)如果都沒有搞懂,又何來擴(kuò)展呢?

在MVC模式下,通過實(shí)現(xiàn)IControllerFactory接口的對(duì)象來獲取當(dāng)前請(qǐng)求的控制器對(duì)象,實(shí)現(xiàn)IControllerFactory接口的對(duì)象也就是控制器的創(chuàng)建工廠。

簡(jiǎn)單看下IControllerFactory

//
  // 摘要:
  //   定義控制器工廠所需的方法。
  public interface IControllerFactory
  {
    //
    // 摘要:
    //   使用指定的請(qǐng)求上下文來創(chuàng)建指定的控制器。
    //
    // 參數(shù):
    //  requestContext:
    //   請(qǐng)求上下文。
    //
    //  controllerName:
    //   控制器的名稱。
    //
    // 返回結(jié)果:
    //   控制器。
    IController CreateController(RequestContext requestContext, string controllerName);
    //
    // 摘要:
    //   獲取控制器的會(huì)話行為。
    //
    // 參數(shù):
    //  requestContext:
    //   請(qǐng)求上下文。
    //
    //  controllerName:
    //   你想要獲取器其會(huì)話行為的控制器的名稱。
    //
    // 返回結(jié)果:
    //   控制器的會(huì)話行為。
    SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName);
    //
    // 摘要:
    //   釋放指定的控制器。
    //
    // 參數(shù):
    //  controller:
    //   控制器。
    void ReleaseController(IController controller);
  }

一個(gè)Http請(qǐng)求過來,選擇哪個(gè)控制器是通過MvcHandler來處理的

控制器工廠是通過ControllerBuilder的Current屬性提供給MvcHandler使用的

下面的代碼是反編譯過來的,簡(jiǎn)單看下即可(因?yàn)槲乙獦?biāo)記黃色高亮部分,所以沒有折疊)

internal ControllerBuilder ControllerBuilder
{
  get
  {
    if (this._controllerBuilder == null)
    {
      this._controllerBuilder = ControllerBuilder.Current;
    }
    return this._controllerBuilder;
  }
  set
  {
    this._controllerBuilder = value;
  }
}
public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState
{
  // Fields
  private ControllerBuilder _controllerBuilder;
  private static readonly object _processRequestTag;
  internal static readonly string MvcVersion;
  public static readonly string MvcVersionHeaderName;

  // Methods
  static MvcHandler();
  public MvcHandler(RequestContext requestContext);
  protected internal virtual void AddVersionHeader(HttpContextBase httpContext);
  protected virtual IAsyncResult BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, object state);
  protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state);
  protected internal virtual void EndProcessRequest(IAsyncResult asyncResult);
  private static string GetMvcVersionString();
  protected virtual void ProcessRequest(HttpContext httpContext);
  protected internal virtual void ProcessRequest(HttpContextBase httpContext);
  private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory);
  private void RemoveOptionalRoutingParameters();
  IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData);
  void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result);
  void IHttpHandler.ProcessRequest(HttpContext httpContext);

  // Properties
  internal ControllerBuilder ControllerBuilder { get; set; }
  public static bool DisableMvcResponseHeader { get; [CompilerGenerated] set; }
  protected virtual bool IsReusable { get; }
  public RequestContext RequestContext { get; [CompilerGenerated] private set; }
  bool IHttpHandler.IsReusable { get; }

  // Nested Types
  [Serializable, CompilerGenerated]
  private sealed class <>c
  {
    // Fields
    public static readonly MvcHandler.<>c <>9;
    public static BeginInvokeDelegate<MvcHandler.ProcessRequestState> <>9__20_0;
    public static EndInvokeVoidDelegate<MvcHandler.ProcessRequestState> <>9__20_1;
    public static Func<KeyValuePair<string, object>, bool> <>9__26_0;

    // Methods
    static <>c();
    public <>c();
    internal IAsyncResult <BeginProcessRequest>b__20_0(AsyncCallback asyncCallback, object asyncState, MvcHandler.ProcessRequestState innerState);
    internal void <BeginProcessRequest>b__20_1(IAsyncResult asyncResult, MvcHandler.ProcessRequestState innerState);
    internal bool <RemoveOptionalRoutingParameters>b__26_0(KeyValuePair<string, object> entry);
  }

  [StructLayout(LayoutKind.Sequential)]
  private struct ProcessRequestState
  {
    internal IAsyncController AsyncController;
    internal IControllerFactory Factory;
    internal RequestContext RequestContext;
    internal void ReleaseController();
  }
}

默認(rèn)工廠

默認(rèn)情況下,在ControllerBuilder內(nèi)部會(huì)創(chuàng)建一個(gè)DefaultControllerFactory類型的對(duì)象,以提供處理請(qǐng)求。

DefaultControllerFactory是實(shí)現(xiàn)IControllerFactory接口的。

//
  // 摘要:
  //   表示默認(rèn)情況下已注冊(cè)的控制器工廠。
  public class DefaultControllerFactory : IControllerFactory
  {
    //
    // 摘要:
    //   初始化 System.Web.Mvc.DefaultControllerFactory 類的新實(shí)例。
    public DefaultControllerFactory();
    //
    // 摘要:
    //   使用控制器激活器來初始化 System.Web.Mvc.DefaultControllerFactory 類的新實(shí)例。
    //
    // 參數(shù):
    //  controllerActivator:
    //   實(shí)現(xiàn)控制器激活器接口的對(duì)象。
    public DefaultControllerFactory(IControllerActivator controllerActivator);

    //
    // 摘要:
    //   使用指定的請(qǐng)求上下文來創(chuàng)建指定的控制器。
    //
    // 參數(shù):
    //  requestContext:
    //   HTTP 請(qǐng)求的上下文,其中包括 HTTP 上下文和路由數(shù)據(jù)。
    //
    //  controllerName:
    //   控制器的名稱。
    //
    // 返回結(jié)果:
    //   控制器。
    //
    // 異常:
    //  T:System.ArgumentNullException:
    //   requestContext 參數(shù)為 null。
    //
    //  T:System.ArgumentException:
    //   controllerName 參數(shù)為 null 或?yàn)榭铡?
    public virtual IController CreateController(RequestContext requestContext, string controllerName);
    //
    // 摘要:
    //   釋放指定的控制器。
    //
    // 參數(shù):
    //  controller:
    //   要釋放的控制器。
    public virtual void ReleaseController(IController controller);
    //
    // 摘要:
    //   檢索指定請(qǐng)求上下文和控制器類型的控制器實(shí)例。
    //
    // 參數(shù):
    //  requestContext:
    //   HTTP 請(qǐng)求的上下文,其中包括 HTTP 上下文和路由數(shù)據(jù)。
    //
    //  controllerType:
    //   控制器的類型。
    //
    // 返回結(jié)果:
    //   控制器實(shí)例。
    //
    // 異常:
    //  T:System.Web.HttpException:
    //   controllerType 為 null。
    //
    //  T:System.ArgumentException:
    //   無法分配 controllerType。
    //
    //  T:System.InvalidOperationException:
    //   無法創(chuàng)建 controllerType 的實(shí)例。
    protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType);
    //
    // 摘要:
    //   返回控制器的會(huì)話行為。
    //
    // 參數(shù):
    //  requestContext:
    //   請(qǐng)求上下文。
    //
    //  controllerType:
    //   控制器的類型。
    //
    // 返回結(jié)果:
    //   控制器的會(huì)話行為。
    protected internal virtual SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType);
    //
    // 摘要:
    //   檢索指定名稱和請(qǐng)求上下文的控制器類型。
    //
    // 參數(shù):
    //  requestContext:
    //   HTTP 請(qǐng)求的上下文,其中包括 HTTP 上下文和路由數(shù)據(jù)。
    //
    //  controllerName:
    //   控制器的名稱。
    //
    // 返回結(jié)果:
    //   控制器類型。
    protected internal virtual Type GetControllerType(RequestContext requestContext, string controllerName);
  }

默認(rèn)情況下,Controller類需要提供默認(rèn)的構(gòu)造函數(shù),因?yàn)镈efaultControllerFactory是通過反射來創(chuàng)建Controller對(duì)象實(shí)例的。

如果我們定義的Controller需要通過構(gòu)造函數(shù)創(chuàng)建,或者通過某個(gè)IoC容器管理Controller,可以通過自定義控制器工廠來實(shí)現(xiàn)。

自定義控制器工廠

為什么說這么多關(guān)于控制器工廠的東西呢,其實(shí)Spring.Net就是通過繼承DefaultControllerFactory創(chuàng)建SpringControllerFactory的。

說了這么多就是為了后面可以更容易的理解Spring.Net的控制器工廠源碼罷了。

回歸正題,接著創(chuàng)建自己的控制器工廠。

1.Home控制器內(nèi)容如下

public class HomeController : Controller
  {
    private IUserInfoService UserInfoService { get; set; }
    public HomeController(IUserInfoService userInfoService)
    {
      UserInfoService = userInfoService;
    }
    public ActionResult Index()
    {
      return Content(UserInfoService.GetName());
    }
  }

這里的UserInfoService只是一個(gè)很簡(jiǎn)陋的測(cè)試類,只有一個(gè)GetName()方法用來返回“小明”。

接下來將通過自定義控制器工廠實(shí)現(xiàn)構(gòu)造注入U(xiǎn)serInfoService

2.創(chuàng)建控制器工廠MyControllerFactory

為了方便我直接繼承了DefaultControllerFactory,當(dāng)然也可以通過實(shí)現(xiàn)IControllerFactory來創(chuàng)建

public class MyControllerFactory : DefaultControllerFactory
  {
    private static readonly IBLL.IUserInfoService userInfoService = new BLL.UserInfoService();

    //重寫CreateController
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
      IController controller = null;
      if (controllerName == "Home")
      {
        //如果是我們制定的Home控制器則給其實(shí)例化,并通過構(gòu)造參數(shù)注入userInfoService
        controller = new HomeController(userInfoService);
      }
      else
      {
        //通過默認(rèn)控制器工廠創(chuàng)建控制器
        controller = base.CreateController(requestContext, controllerName);
      }
      return controller;
    }
  }

3.在Global.asax中注冊(cè)

protected void Application_Start()
    {
      MyControllerFactory myControllerFactory = new MyControllerFactory();
      //通過ControllerBuilder設(shè)置制定的控制器工廠
      ControllerBuilder.Current.SetControllerFactory(myControllerFactory);
      AreaRegistration.RegisterAllAreas();
      RouteConfig.RegisterRoutes(RouteTable.Routes);
    }

4.運(yùn)行測(cè)試(神奇不再神奇)

意料之外,情理之中,我們并沒有在控制器中實(shí)例化,結(jié)果卻出來了

(實(shí)例化在工廠中完成了)

Spring.Net注入原理

說了這么多,回頭看看標(biāo)題“Spring.Net是怎么在MVC中實(shí)現(xiàn)注入的”,你倒是說啊,等的花都謝了,連Spring.Net的毛都沒看到.....

其實(shí),如果你是認(rèn)真讀過來的,答案在你心中應(yīng)該已經(jīng)有了。

答案如下

namespace Spring.Web.Mvc
{
  /// <summary>
  /// Controller Factory for ASP.NET MVC
  /// </summary>
  public class SpringControllerFactory : DefaultControllerFactory
  {
    private static IApplicationContext _context;

    /// <summary>
    /// Gets the application context.
    /// </summary>
    /// <value>The application context.</value>
    public static IApplicationContext ApplicationContext
    {
      get
      {
        if (_context == null || _context.Name != ApplicationContextName)
        {
          if (string.IsNullOrEmpty(ApplicationContextName))
          {
            _context = ContextRegistry.GetContext();
          }
          else
          {
            _context = ContextRegistry.GetContext(ApplicationContextName);
          }
        }

        return _context;
      }
    }

    /// <summary>
    /// Gets or sets the name of the application context.
    /// </summary>
    /// <remarks>
    /// Defaults to using the root (default) Application Context.
    /// </remarks>
    /// <value>The name of the application context.</value>
    public static string ApplicationContextName { get; set; }

    /// <summary>
    /// Creates the specified controller by using the specified request context.
    /// </summary>
    /// <param name="requestContext">The context of the HTTP request, which includes the HTTP context and route data.</param>
    /// <param name="controllerName">The name of the controller.</param>
    /// <returns>A reference to the controller.</returns>
    /// <exception cref="T:System.ArgumentNullException">The <paramref name="requestContext"/> parameter is null.</exception>
    /// <exception cref="T:System.ArgumentException">The <paramref name="controllerName"/> parameter is null or empty.</exception>
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
      IController controller;

      if (ApplicationContext.ContainsObjectDefinition(controllerName))
      {
        controller = ApplicationContext.GetObject(controllerName) as IController;
      }
      else
      {
        controller = base.CreateController(requestContext, controllerName);
      }

      AddActionInvokerTo(controller);

      return controller;
    }

    /// <summary>
    /// Retrieves the controller instance for the specified request context and controller type.
    /// </summary>
    /// <param name="requestContext">The context of the HTTP request, which includes the HTTP context and route data.</param>
    /// <param name="controllerType">The type of the controller.</param>
    /// <returns>The controller instance.</returns>
    /// <exception cref="T:System.Web.HttpException">
    ///   <paramref name="controllerType"/> is null.</exception>
    /// <exception cref="T:System.ArgumentException">
    ///   <paramref name="controllerType"/> cannot be assigned.</exception>
    /// <exception cref="T:System.InvalidOperationException">An instance of <paramref name="controllerType"/> cannot be created.</exception>
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
      IController controller = null;

      if (controllerType != null)
      {
        var controllers = ApplicationContext.GetObjectsOfType(controllerType);
        if (controllers.Count > 0)
        {
          controller = (IController)controllers.First().Value;
        }
      }

      if (controller == null)
      {
        //pass to base class for remainder of handling if can't find it in the context
        controller = base.GetControllerInstance(requestContext, controllerType);
      }
      
      AddActionInvokerTo(controller);

      return controller;
    }

    /// <summary>
    /// Adds the action invoker to the controller instance.
    /// </summary>
    /// <param name="controller">The controller.</param>
    protected virtual void AddActionInvokerTo(IController controller)
    {
      if (controller == null)
        return;

      if (typeof(Controller).IsAssignableFrom(controller.GetType()))
      {
        ((Controller)controller).ActionInvoker = new SpringActionInvoker(ApplicationContext);
      }
    }
  }
}

關(guān)于代碼我想就不用過多解釋了,有了上面的知識(shí)基礎(chǔ),這就是一看就懂的那種。

算了,我還是說一下CreateController方法吧,防止有不熟悉Spring.Net的小伙伴。

ApplicationContext:這就是相當(dāng)于IoC容器的東西

ApplicationContext.ContainsObjectDefinition(controllerName):返回容器中是否存在名稱為controllerName的對(duì)象

總結(jié)

仔細(xì)品味每一行代碼,會(huì)發(fā)現(xiàn)任何東西都沒有表面上那么簡(jiǎn)單,每一個(gè)實(shí)現(xiàn)的背后都值得深入研究。

碼了這么長(zhǎng)時(shí)間,希望能對(duì)正在閱讀的你有所幫助。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringMVC使用RESTful接口案例詳解

    SpringMVC使用RESTful接口案例詳解

    RESTful是一種web軟件風(fēng)格,它不是標(biāo)準(zhǔn)也不是協(xié)議,它不一定要采用,只是一種風(fēng)格,它倡導(dǎo)的是一個(gè)資源定位(url)及資源操作的風(fēng)格,這篇文章主要介紹了SpringBoot使用RESTful接口
    2022-11-11
  • Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解

    Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解

    這篇文章主要介紹了Java中的interrupt、interrupted和isInterrupted方法區(qū)別詳解,interrupt用于中斷線程,調(diào)用該方法的線程的狀態(tài)將會(huì)被設(shè)置為中斷狀態(tài),線程中斷僅僅是設(shè)置線程的中斷狀態(tài)位,并不會(huì)停止線程,需要用戶自己去監(jiān)視線程的狀態(tài)并作出處理,需要的朋友可以參考下
    2023-12-12
  • Java實(shí)現(xiàn)導(dǎo)入導(dǎo)出Excel文件的方法(poi,jxl)

    Java實(shí)現(xiàn)導(dǎo)入導(dǎo)出Excel文件的方法(poi,jxl)

    這篇文章主要介紹了Java實(shí)現(xiàn)導(dǎo)入導(dǎo)出Excel文件的方法(poi,jxl),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • tomcat301與java301解析

    tomcat301與java301解析

    這篇文章主要介紹了omcat301與java301,有需要的朋友可以參考一下
    2014-01-01
  • IDEA配置碼云Gitee的使用詳解

    IDEA配置碼云Gitee的使用詳解

    這篇文章主要介紹了IDEA配置碼云Gitee的使用,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • IDEA如何實(shí)現(xiàn)顯示類的所有方法

    IDEA如何實(shí)現(xiàn)顯示類的所有方法

    這篇文章主要介紹了IDEA如何顯示類的所有方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 深入理解Java中的HashMap

    深入理解Java中的HashMap

    HashMap是Java程序員使用頻率最高的用于映射(鍵值對(duì))處理的數(shù)據(jù)類型。隨著JDK(Java Developmet Kit)版本的更新,JDK1.8對(duì)HashMap底層的實(shí)現(xiàn)進(jìn)行了優(yōu)化,例如引入紅黑樹的數(shù)據(jù)結(jié)構(gòu)和擴(kuò)容的優(yōu)化等。本文將深入探討HashMap的結(jié)構(gòu)實(shí)現(xiàn)和功能原理
    2021-06-06
  • 一篇文章帶你了解Java之關(guān)鍵字和保留字

    一篇文章帶你了解Java之關(guān)鍵字和保留字

    Java 保留字列表 (依字母排序 共14組) : Java保留字是指現(xiàn)有Java版本尚未使用 但以后版本可能會(huì)作為關(guān)鍵字使用,希望本篇文章能給您帶來幫助
    2021-08-08
  • Mybatis SQL日志如何轉(zhuǎn)換為可執(zhí)行sql

    Mybatis SQL日志如何轉(zhuǎn)換為可執(zhí)行sql

    這篇文章主要介紹了Mybatis SQL日志如何轉(zhuǎn)換為可執(zhí)行sql問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • mybatis-plus update更新操作的三種方式(小結(jié))

    mybatis-plus update更新操作的三種方式(小結(jié))

    本文主要介紹了mybatis-plus update更新操作的三種方式,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10

最新評(píng)論

任丘市| 夏津县| 乌拉特前旗| 南溪县| 山东省| 贵溪市| 阜新市| 勐海县| 德阳市| 冷水江市| 龙门县| 江永县| 安多县| 吴旗县| 东源县| 沙河市| 兴宁市| 朔州市| 洪湖市| 文登市| 图片| 江门市| 博野县| 开封市| 游戏| 泰和县| 香港| 嘉义市| 德庆县| 波密县| 中卫市| 红桥区| 泰顺县| 东平县| 垫江县| 余庆县| 安塞县| 曲阜市| 沙坪坝区| 福海县| 多伦县|