当前 Spring.Net当前已经发布了0.6版本,其网站上公布的路线图
  • IoC Container (0.6)
  • AOP (0.7)
  • Remoting Factory Objects (0.8)
  • Database - DAO/Templates (0.9)

    我现在每天花一些时间来跟踪其源代码的变化。spring.net代码质量相当令人满意,现在每天 cvs都有一些检入。在cvs中,Spring.Services 项目已经创建 ,Spring.Data项目已经创建,近几天,一个Spring.Pool的namespace已经加入的Spring.Core项目,用来实现对象池的功能。

    一个讨论spring.web的实现建议的邮件也相当有意思 sourceforge.net/mailarchive/forum.php?thread_id=5946064&forum_id=40049

    很早以前,我在blog上介绍spring container功能,同那时相比,工程有了很大的变化,iesi.collections.dll现在已经合并到Spring.Core项目中,命名空间是Spring.Collections. Spring.Collections 主要解决了.net 中没有Set的缺陷
    现在Spring.Context项目已经完成,Spring.Context是Spring.Objects的扩展和延伸,除了①对象工厂(容器)功能外(避免singleton的滥用,实现IListableObjectFactory接口)
    Spring.Context更提供以下多个功能

    ②支持国际化
    ③资源访问
    ④事件传播

    在使用上,通常建议直接使用IApplicationContext,而不是IObjectFactory,IObjectFactory比IApplicationContext而言主要适用仅使用容器功能的场合

    这次的修订以介绍Spring.Context为主,依次介绍其容器、国际化、资源访问,事件传播。这是第一篇,介绍其容器功能。我的文笔很差,如果有行文不通的地方,希望大家指出,我会修改。

    下面有些词汇可能会混用,先在这里注明
  • 容器/container /对象工厂
  • ApplicationContext/IApplicationContext/应用程序上下文


    快速开始



    从 cvs中下载源代码, sourceforge.net/projects/springnet/ 或从 .net 评测网 下载

    1、编译
    2、新建项目,引用log4net.dll,和spring.core.dll,Spring.Context.dll
    3、创建一个简单的Person类,具有两个属性 Name,Address;
    public class Person
    {
    public Person(String name,String address)
    {
    this._name=name;
    this._address=address;
    }
    private String _name;
    private String _address;
    public String Name
    {
    get{return this._name;}
    set{this._name=value;}
    }
    public String Address
    {
    set{this._address=value;}
    get{return this._address;}
    }
    }
    

    4、创建applicationcontext配置文件,现在你有多种方案
    通过应用程序配置文件app.config
    <?xml version="1.0" encoding="utf-8" ?>
    < <configSections>
    <sectionGroup name="spring">
    <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
    <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </sectionGroup>
    </configSections>
    <spring>
    <context>
    <resource uri="config://spring/objects"/>
    </context>
    <objects>
    <!--您的对象定义 -->
    <object name="xx" type="xxx"/>
    </objects>
    </objects>
    </configuration>
    

    利用单独的xml 文件
    <?xml version="1.0" encoding="utf-8" ?>
    <objects>
    <!--您的对象定义 -->
    <object name="xx" type="xxx"/>
    </objects>
    </configuration>
    

    如果你使用应用程序配置文件,一般可如下调用
    IApplicationContext context=(IApplicationContext)System.Configuration.ConfigurationSettings.GetConfig("spring/context");
    


    如果你使用单独的xml 文件,可如下调用
    IApplicationContext context=(IApplicationContext)new XmlApplicationContext("applicationcontext.xml");
    


    依赖注入


    关于依赖注入的进一步信息可参阅这里, www.martinfowler.com/articles/injection.html (有gigix翻译的中文版本)。这里我不再解释其含义。
    Spring 主要支持ioc 的两种模式setter和constructor,举例如下

    构造函数注入
    对象暴露一个或多个构造函数,容器调用相应的构造函数设置属性值
    <object name="jjx" type="WindowsApplication1.Person,WindowsApplication1">
    <constructor-arg description="Name"><value>jjx</value></constructor-arg>
    <constructor-arg description="Address"><value>zj</value></constructor-arg>
    </object>
    


    set属性注入
    对象暴露一个或多个setter属性,容器调用相应的属性设置属性值
    <object name="jxb" type="WindowsApplication1.Person,WindowsApplication1">
    <property name="Name"><value>jjx</value></property>
    <property name="Address"><value>zj</value></property>
    </object>
    



    Contextualized Dependency Lookup

    这是通过实现IApplicationContextAware 接口,组件一旦实现该接口,就可以得到一个IApplicationContext 接口的实例,则可以通过其获取其它组件
    public class  SaleOrderService : IApplicationContextAware
    {
    private SaleOrderDao dao;
    public IApplicationContext ApplicationContext
    {
    set
    {
    dao=(SaleOrderDao)value.GetObject("saleOrderDao");
    }
    }
    }
    

    建议:当前ApplicationObjectSupport已经加入到Spring.Context中,你可以直接继承它

    上下文注入需要依赖于spring的特定接口,因此不建议使用


    配置文件提示



    关于配置文件的具体写法,请参照src\spring.core\objects\factory\spring-objects.dtd ,配置文件主要就是在描述对象是如何组装的

    1、简单属性
    一般使用value元素,如
    <property name="zip"><value>315400</value></property>
    



    2、Spring 支持的四种复杂的属性类型(map,list,set,name-values)
    dictionary - IDictonary,如一个电话属性

    代码:
       private IDictionary _phone;
    public IDictionary Phone
    {
    get { return _phone; }
    set { this._phone = value; }
    }
    

    xml描述:
    <property name="Phone">
    <dictionary>
    <entry key="home">
    <value>xxxx</value>
    </entry>
    <entry key="mobile">
    <value>xxxxxx</value>
    </entry>
    </dictionary>
    </property>
    


    list - 映射为IList ,也可以是数组,如一个Childrens属性

    代码:
      private IList _childrens;
    public IList Childrens
    {
    set { this._childrens = value; }
    get { return this._childrens; }
    }
    

    xml 描述
     <property name="Childrens">
    <list>
    <ref object="jyf"></ref>
    </list>
    </property>
    


    name-values .net 版本没有java 版本中的props,而是使用name-values,其对应的对象是System.Collections.Specialized.NameValueCollection,和map 不同的是其值为字符串
    代码:
    private NameValueCollection _books;
    public NameValueCollection Books
    {
    get { return this._books; }
    set { this._books = value; }
    }
    

    xml 描述
     <property name="Books">
    <name-values>
    <add key="7-89494-030-5" value="Visual Basic.Net技术内幕"/>
    <add key="7-5083-2177-4" value="Essential .net"/>
    </name-values>
    </property>
    

    注: spring.net创建了java Properties 对象的等价物Spring.Util.Properties

    Set 实现Spring.Collections.ISet ,写法上类似list,但要求其中的对象必须不相同


    3、null

    使用null元素代表一个null
    <property name="SaleOrderDao"><null/></property>
    


    4、 引用对象
    使用<ref object="xxx"/>或<ref local="xxx"/>
    区别是local只从当前applicationcontext查询<ref local="object name"/>,object在当前ApplicationContext不存在的情况下会查询其父ApplicationContext

    进阶话题



    singleton
    spring 容器中的对象默认是singleton的,如果要非singleton的对象,你需要将singleton attribute设置为false
    <object name="xxx" class="xxx" singleton="false"/>
    singleton这种设计模式在早先运用的较多,现在则是被批评的较多,因为singleton在多线程中需要注意一些问题(参见我的多线程一文)。而通过spring 的singleton,你可以像平时一样写代码,其它的交由spring去做。

    对象生命周期
    通过实现IInitializingeObject和IDisposable接口,替代的方法是使用init-method和destroy-method attribute,后者不需要显式实现接口
    具体参见 Spring重要接口介绍 一文

    lazy-init
    仅针对设置了singleton="true"的对象而言,即在需要时才创建该对象,默认的spring在容器初始化时创建对象的实例(singleton)

    SpringUtil 类
    对于一个依赖于spring的项目而言,你需要为IApplicationContext创建一个全局引用
    下面是一个简单实现(这里,我做了一些修改:首先IApplicationContext应该是线程共享的,当然线程不共享可以避免许多问题。第二应该尽量少在项目中引用IApplicationContext.第三:在spring.web项目中,一个WebApplicationContext.Current属性也可以直接使用

    public class SpringUtil
    {
    private static IApplicationContext context=null;
    private SpringUtil()
    {
    }
    public static void Close()
    {
    if (context!=null)
    {
    AbstractApplicationContext c=(context as AbstractApplicationContext);
    if (c!=null)
    c.Close();
    context=null;
    }
    }
    public static IApplicationContext Context
    {
    get
    {
    if (context==null)
    {
    lock(typeof(SpringUtil)
    {
    if (context!=null)
    context=new XmlApplicationContext("applicationcontext.xml");
    }
    }
    return context;
    }
    }
    }
    
  • posted on 2009-06-09 13:35  胜者为王  阅读(1407)  评论(0编辑  收藏  举报