主要内容

  1.WindsorContainer分析

  2.MicroKernel分析

  3.注册组件流程

  一.WindsorContainer分析

  WindsorContainer是Castle的IOC容器,也是它的一个核心,先来看一下WindsorContainer在Castle中所处的位置:

  图1

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

  图2

  二.MicroKernel分析

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

  图3

  三.注册组件流程

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

双击代码全选
1
2
3
4
5
6
7
8
9
10
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);
}

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

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public virtual void AddComponent(String key, Type classType)
{
  if (key == null) throw new ArgumentNullException("key");
  if (classType == null) throw 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 == null) throw new ArgumentNullException("key");
  if (serviceType == null) throw new ArgumentNullException("serviceType");
  if (classType == null) throw new ArgumentNullException("classType");
  
  ComponentModel model = ComponentModelBuilder.BuildModel(key, serviceType, classType, null);
  RaiseComponentModelCreated(model);
  IHandler handler = HandlerFactory.Create(model);
  RegisterHandler(key, handler);
}

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

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
}

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

双击代码全选
1
2
3
4
5
6
7
8
9
10
11
12
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() );
}

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

双击代码全选
1
2
3
4
5
6
protected virtual void RaiseComponentModelCreated(ComponentModel model)
{
  ComponentModelDelegate eventDelegate = (ComponentModelDelegate) events[ComponentModelCreatedEvent];
  if (eventDelegate != null) eventDelegate(model);
}

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

双击代码全选
1
2
3
4
5
6
7
public virtual IHandler Create(ComponentModel model)
{
  IHandler handler = new DefaultHandler(model);
  handler.Init(kernel);
  return handler;
}

Castle IOC容器内幕故事(上)的更多相关文章

  1. Castle IOC容器内幕故事(下)

    主要内容 1.ComponentModelBuilder 和 Contributors 2.Contributors分析 3.Handles分析 4.ComponentActivator分析 一.Co ...

  2. Castle IOC容器组件生命周期管理

    主要内容 1.生命处理方式 2.自定义生命处理方式 3.生命周期处理 一.生命处理方式 我们通常创建一个组件的实例使用new关键字,这样每次创建出来的都是一个新的实例,如果想要组件只有一个实例,我们会 ...

  3. Castle IOC容器与Spring.NET配置之比较

    我本人对于Spring.NET并不了解,本文只是通过一个简单的例子来比较一下两者配置之间的区别.在Castle IOC容器中,提出了自动装配(Auto-Wiring)的概念,即由容器自动管理组件之间的 ...

  4. Castle IOC容器快速入门

    主要内容 1.为什么要IOC 2.什么是Castle IOC容器 3.快速入门示例 4.几个重要的概念 一,为什么要IOC IOC(控制反转或者叫依赖注入)Martin Fowler大师在他的文章中已 ...

  5. Castle IOC容器构建配置详解(二)

    主要内容 1.基本类型配置 2.Array类型配置 3.List类型配置 4.Dictionary类型配置 5.自定义类型转换 一.基本类型配置 在Castle IOC的配置文件中,大家可能都已经注意 ...

  6. Castle IOC容器构建配置详解(一)

    主要内容 1.配置什么 2.几种配置方式 3.Include 介绍 4.Properties介绍 5.条件状态 一.配置什么 Castle IOC中并不像Spring.net那样贯穿着一个思想就是一切 ...

  7. Castle IOC容器实践之FactorySupport Facility

    PDF版本下载:http://file.ddvip.com/2008_10/1223538519_ddvip_4853.rar示例代码下载:http://file.ddvip.com/2008_10/ ...

  8. Spring IoC容器与应用上下文的设计与实现

    一.前言 写这篇博文的主要目的如下: 通过相关类和接口分析IoC容器到底长什么样. 阐述笔者对Spring上下文和容器的理解. 介绍重要的类辅助理解SpringBoot的启动流程. 二.Spring ...

  9. 【最简单IOC容器实现】实现一个最简单的IOC容器

    前面DebugLZQ的两篇博文: 浅谈IOC--说清楚IOC是什么 IoC Container Benchmark - Performance comparison 在浅谈IOC--说清楚IOC是什么 ...

随机推荐

  1. 【自动化测试】Selenium 2.0 学习笔记

    定位下拉框元素,要记得先把鼠标挪过去再进行定位. 定位元素用的是find_element_by.... python的模块化还要去思考下 unittest框架使用的时候,py文件命名不要用unitte ...

  2. SELinux Mysql的error-log文件位置的指定

    SELinux下,在配置my.cnf时,必须指定error-log的位置在/var/log/下, 否则error的默认位置为例如 /var/lib/mysql下的tyoyi.server.err文件, ...

  3. 决定undo表空间的大小

    1.查询每秒最高需要的undo的数据块[每个块8k大小] sys)) from v$undostat; )) --------------------------------------------- ...

  4. JVM——垃圾收集算法

    1.标记-清除算法 最基础的收集算法,如其名,算法为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. 两个不足: 1)效率问题,标记和清除两个过程的效率 ...

  5. 【转】Github轻松上手5-站在巨人的肩膀上(Fork)

    转自:http://blog.sina.com.cn/s/blog_4b55f6860100zzj3.html 有时候你可能想给别人的项目出把力,或者想以别人的项目作为自己项目的起点,在Github里 ...

  6. apple-touch-icon,shortcut icon和icon的区别

    apple-touch-icon 可以了解到这是一个类似网站favicon的图标文件,用来在iphone和ipod上创建快捷键时使用. 这个文件应当是png格式,57x57像素大小,放在网站根目录之下 ...

  7. 常见排序算法基于JS的实现

    一:冒泡排序 1. 原理 a. 从头开始比较相邻的两个待排序元素,如果前面元素大于后面元素,就将二个元素位置互换 b. 这样对序列的第0个元素到n-1个元素进行一次遍历后,最大的一个元素就“沉”到序列 ...

  8. ADO.NET+Access: 3,参数 @departmentName 没有默认值

    ylbtech-Error-ADO.NET+Access: 3,参数 @departmentName 没有默认值. 1.A,错误代码返回顶部  3,参数 @departmentName 没有默认值. ...

  9. 《C++ primer》--第1,2章小结

    来源:http://blog.csdn.net/wangqiulin123456/article/details/8483853 1.变量初始化:      定义变量时,应该给变量赋初始值,除非确定将 ...

  10. android 性能优化大纲

    性能优化系列 分为三个部分:视图篇 逻辑篇  和代码规范篇 . ------2016/9/6  视图篇      主要涵盖视图树层级优化.自定义视图.图片优化,常用布局性能缺陷等多个方面 .把平常经常 ...