zoukankan      html  css  js  c++  java
  • Castle IOC容器内幕故事(上)

    摘要:在快速入门指南篇中,我们对于Castle IOC容器的使用已经有了一个直观的认识。本文将在这基础上进一步对Castle IOC容器的结构及其注册组件的过程做一个深入的分析,让我们开始Castle IOC的内幕故事吧。

     

    主要内容

    1WindsorContainer分析

    2MicroKernel分析

    3.注册组件流程

     

    一.WindsorContainer分析

    WindsorContainerCastleIOC容器,也是它的一个核心,先来看一下WindsorContainerCastle中所处的位置:

    1

    WindsorContainer构建于MicroKernel之上,MicroKernel仅仅是提供了一个IOC的容器,非常的轻巧,它只依赖于Castle.Model一个程序集,但它的可扩展能力却很强,后面会讲到;可以这么理解,WindsorContainer为我们提供了一个Façade,它封装了MicroKernel,并且提供了一些扩展点,但它的核心仍然是Microkernel如下图所示:

    2

    二.MicroKernel分析

    既然MicroKernelWindsorContainer的核心,那我们就来看一下MicroKernel的结构,从下面的结构图中,可以看到MicroKernel的组成主要有SubSystemComponentsFacilities几个部分,SubSystem主要用来处理一些扩展功能,如配置、类型转换等,我们也可以实现自己的SubSystemComponents称为组件,在快速入门指南中我已经提到了,这里再说一下,服务是一个个的接口,接口约定了服务,从而使随意替换服务的实现对使用接口服务的代码没有任何的影响,组件是一个可重用的程序单元,它实现了某个接口,并仅仅只实现了这一个良好的接口,也就是说,组件是实现了某个服务接口的类;Facilities我们称之为扩张单元,如果我们想扩张容器的功能,可以通过创建扩张单元来实现,我们可以在扩张单元里面订阅容器事件,给组件附加属性,建立拦截器,控制组件生命周期等,扩张单元是以一种插件的形式存在的,所以非常便于扩展,可以编写自己的扩张单元,后面我会写Castle自带的一些扩张单元的使用。MicroKernel的结构如下图:

    3

    三.注册组件流程

    现在我们来看一下当注册一个组件时,容器做了什么?

    public virtual void AddComponent(String key, Type classType)

    {

        _kernel.AddComponent(key, classType);

    }


     

    public virtual void AddComponent(String key, Type serviceType, Type classType)

    {

        _kernel.AddComponent(key, serviceType, classType);

    }


    // http://terrylee.cnblogs.com


    可以看到,WindsorContainer仅仅是调用了MicroKernel的方法来完成组件的注册,它只是对MicroKernel做了一次封装,核心的功能都由MicroKernel来完成,看一下MicroKernel中的AddComponent()方法的实现

    public virtual void AddComponent(String key, Type classType)

    {

        
    if (key == nullthrow new ArgumentNullException("key");

        
    if (classType == nullthrow new ArgumentNullException("classType");

     

        ComponentModel model 
    = ComponentModelBuilder.BuildModel(key, classType, classType, null);

        RaiseComponentModelCreated(model);

        IHandler handler 
    = HandlerFactory.Create(model);

        RegisterHandler(key, handler);

    }


     

    public virtual void AddComponent(String key, Type serviceType, Type classType)

    {

        
    if (key == nullthrow new ArgumentNullException("key");

        
    if (serviceType == nullthrow new ArgumentNullException("serviceType");

        
    if (classType == nullthrow new ArgumentNullException("classType");

     

        ComponentModel model 
    = ComponentModelBuilder.BuildModel(key, serviceType, classType, null);

        RaiseComponentModelCreated(model);

        IHandler handler 
    = HandlerFactory.Create(model);

        RegisterHandler(key, handler);

    }


    // http://terrylee.cnblogs.com

    先做一些必要的异常处理,然后为当前组件创建ComponentModel实例,ComponentModel获取当前组件的详细元信息,而且这个信息在容器中的任何地方都可以使用,所以ComponentModel其实就是组件的一个“元信息库”。创建ComponentModel的过程如下:

    public ComponentModel BuildModel(String key, Type service, 

        Type classType, IDictionary extendedProperties)

    {

        ComponentModel model 
    = new ComponentModel(key, service, classType);


        
    if (extendedProperties != null)

        
    {

            model.ExtendedProperties 
    = extendedProperties;

        }


        
    foreach(IContributeComponentModelConstruction contributor in contributors)

        
    {

            contributor.ProcessModel( kernel, model );

        }


        
    return model;
    }

    // http://terrylee.cnblogs.com

    创建ComponentModel的过程其实就是调用contributor来对组件进行处理,它会按照顺序对添加进来的contributor依次调用,在DefaultComponentModelBuilder一共注册了八个Contributor,分别为:

    protected virtual void InitializeContributors()

    {

        AddContributor( 
    new ConfigurationModelInspector() );

        AddContributor( 
    new LifestyleModelInspector() );

        AddContributor( 
    new ConstructorDependenciesModelInspector() );

        AddContributor( 
    new PropertiesDependenciesModelInspector() );

        AddContributor( 
    new MethodMetaInspector() );

        AddContributor( 
    new LifecycleModelInspector() );

        AddContributor( 
    new ConfigurationParametersInspector() );

        AddContributor( 
    new InterceptorInspector() );

    }


    // http://terrylee.cnblogs.com

    这八个Contributor形成了一个处理组件的流程,它们涵盖了组件处理流程中的配置,生命周期,构造函数依赖,属性依赖等方面,每一个Contributor只负责某一方面的事情。再下来一步就是发出ComponentModelCreated事件了,这步的操作很简单

    protected virtual void RaiseComponentModelCreated(ComponentModel model)

    {

        ComponentModelDelegate eventDelegate 
    = (ComponentModelDelegate) events[ComponentModelCreatedEvent];

        
    if (eventDelegate != null) eventDelegate(model);

    }


    // http://terrylee.cnblogs.com

    现在ComponentModel创建完成,该是创建IHandler了,IHandler并不做创建组件的工作,它主要的功能是创建ComponentActivator,而ComponentActivator则是完成容器的组件创建工作,它首先会根据ComponentModel“信息库”检查相关的依赖,检查通过后根据生命周期管理来创建不同类型的组件,创建DefaultHandler的代码如下:

    public virtual IHandler Create(ComponentModel model)

    {

        IHandler handler 
    = new DefaultHandler(model);

        handler.Init(kernel);

        
    return handler;

    }


    // http://terrylee.cnblogs.com

    最后发出ComponentRegisteredHandlerRegistered事件,完成整个组件的注册过程。

    Castle IOC容器内幕故事(下)   

    参考资料

    Castle的官方网站http://www.castleproject.org
  • 相关阅读:
    使用javap分析Java的字符串操作
    使用javap深入理解Java整型常量和整型变量的区别
    分享一个WebGL开发的网站-用JavaScript + WebGL开发3D模型
    Java动态代理之InvocationHandler最简单的入门教程
    Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)
    Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)
    Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)
    Java实现 LeetCode 541 反转字符串 II(暴力大法)
    Java实现 LeetCode 541 反转字符串 II(暴力大法)
    Java实现 LeetCode 541 反转字符串 II(暴力大法)
  • 原文地址:https://www.cnblogs.com/Terrylee/p/378047.html
Copyright © 2011-2022 走看看