zoukankan      html  css  js  c++  java
  • [Spring.NET IoC]入门

    [Spring.NET IoC] 之一:基本信息

    作者:Q.yuhen  来源:Q.yuhen  
    Spring.NET 移植自著名的 Java 开源项目 —— Spring,借助于 .NET 强大的反射机制,甚至拥有比原 Java 版本更强大的功能。只是不知道什么原因,在 .NET 领域似乎没有多少热度,其影响力甚至不如 Castle。因准备在个人项目中使用 IoC,因此花些时间对 Spring.NET 和 Castle 都作一些了解,本文权作学习笔记。

    Spring.NET 的宣传口号中有 "non-invasiveness. Quite simply" 的字样,表示是非入侵且易用的,当然作为一个IoC容器,这些都是最基本的特征。

    在 Spring.NET IoC 中最核心的内容应该是 IObjectFactory、IApplicationContext、IObjectDefinition 这三个接口了。IObjectFactory 是核心容器接口,负责管理容器内的注入对象,而 IApplicationContext 则是 IObjectFactory 的继承,它扩展了一些功能。IObjectDefinition 是注入对象的定义接口,供 IObjectFactory / IApplicationContext 调用。

    大多数时候我们会选择 IApplicationContext 接口的实现类来操控 Spring.NET IoC 容器。

    1. Spring.Context.Support.ContextRegistry
    将配置信息写入 app.config / web.config 时所使用该类。

    2. Spring.Context.Support.XmlApplicationContext
    使用独立的 xml 配置文件,或者使用多个 xml 配置文件时,使用该类。

    3. Spring.Context.Support.StaticApplicationContext
    直接在代码中装配容器时,使用该类。

    当然,你还可以使用 Spring.Objects.Factory.Xml.XmlObjectFactory 等直接实现 IObjectFactory 的类型。

    作为该篇的结束,写一个简单的 "Hello World" 尝试一下。
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using Spring.Core;
    using Spring.Context;
    using Spring.Context.Support;

    namespace ConsoleApplication1.SpringNet
    {
      public class HelloWorld
      {
        public override string ToString()
        {
          return "Hello, World!";
        }
      }

      public class Program
      {
        static void Main(string[] args)
        {
          StaticApplicationContext context = new StaticApplicationContext();
          context.RegisterPrototype("HelloWorld", typeof(HelloWorld), null);

          object o = context.GetObject("HelloWorld");
          Console.WriteLine(o);
        }
      }
    }

    [Spring.NET IoC] 之二:配置文件

    Spring.NET IoC 支持2种配置文件方式:

    1. 应用程序配置文件

    app.config / web.config
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <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 xmlns="http://www.springframework.net">
          <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" >
          </object>
        </objects>

      </spring>
    </configuration>

    test.cs
          IApplicationContext context = ContextRegistry.GetContext();
          object o = context.GetObject("HelloWorld");

    2. 独立配置文件

    springtest.xml
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">
      
      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
      </object>
    </objects>

    test.cs
    IApplicationContext context = new XmlApplicationContext(@"springtest.xml");
    object o = context.GetObject("HelloWorld");

    建议使用独立的配置文件,应用程序配置文件已经被塞入太多内容了。Spring.NET 还支持很多高级的

    [Spring.NET IoC] 之三:获取对象 

    依照第二篇的配置文件,我们可以初步注入我们所需的类型。本篇将记录获取对象的不同方法。

    1. 构造方法创建对象

    这种方式最常见,大多数时候我们都会采取此方式获取对象。如果目标对象需要提供构造参数,我们也可以在配置文件中提供。
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
        <constructor-arg name="name" value="Tom" />
        <constructor-arg name="age" value="234" />
      </object>
    </objects>
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using Spring.Core;
    using Spring.Context;
    using Spring.Context.Support;

    namespace ConsoleApplication1.SpringNet
    {
      public class HelloWorld
      {
        private string name;
        private int age;

        public HelloWorld(string name, int age)
        {
          this.name = name;
          this.age = age;
        }

        public override string ToString()
        {
          return String.Format("Name={0}; Age={1}", name, age);
        }
      }

      public class Program
      {
        static void Main(string[] args)
        {
          IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
          object o = context.GetObject("HelloWorld");
          Console.WriteLine(o);
        }
      }
    }

    需要注意的是 Spring.NET IoC 缺省对象创建方式是 "Singleton",我们写个例子验证一下。
    object o = context.GetObject("HelloWorld");
    object o2 = context.GetObject("HelloWorld");
    Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true

    我们只需在配置文件中添加一个标记即可改变为非 Singleton 方式。
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" singleton="false">
        <constructor-arg name="name" value="Tom" />
        <constructor-arg name="age" value="234" />
      </object>
    </objects>

    2. 静态工厂方法创建对象

    我们提供另外一个 HelloWorld 类,该类型没有公用构造方法,只能通过静态方法创建对象。
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using Spring.Core;
    using Spring.Context;
    using Spring.Context.Support;

    namespace ConsoleApplication1.SpringNet
    {
      public class HelloWorld
      {
        private HelloWorld()
        {
        }

        public static HelloWorld Create()
        {
          return new HelloWorld();
        }
      }

      public class Program
      {
        static void Main()
        {
          IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");

          object o = context.GetObject("HelloWorld");
          object o2 = context.GetObject("HelloWorld");
          Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
        }
      }
    }

    对于这种方式,我们只需指定 "factory-method" 即可,需要注意的是所指定的方法必须是静态方法。
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" factory-method="Create">
      </object>
    </objects>

    3. 实例工厂方法创建对象

    修改上面的例子。在下面的代码中我们必须通过一个名为 Creator 的类才能创建 HelloWorld。
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using Spring.Core;
    using Spring.Context;
    using Spring.Context.Support;

    namespace ConsoleApplication1.SpringNet
    {
      public class Creator
      {
        public HelloWorld Create()
        {
          return new HelloWorld();
        }
      }

      public class HelloWorld
      {
        internal HelloWorld()
        {
        }
      }

      public class Program
      {
        static void Main()
        {
          IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
          
          object o = context.GetObject("HelloWorld");
          object o2 = context.GetObject("HelloWorld");
          Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true
        }
      }
    }
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" factory-method="Create" factory-object="Creator" />
      <object id="Creator" type="ConsoleApplication1.SpringNet.Creator, Learn.CUI" />
    </objects>

    通过上面的配置文件我们知道,我们必须提供一个 Creator 的注入声明,同时要为 HelloWorld 指定创建者的 "factory-object" 和 "factory-method"。

    4. 对象初始化方法

    我们可以在配置文件中使用 "init-method" 指定类型构造方法以外的初始化方法。该方法会在对象构造方法之后被容器调用执行,以便我们完成一些初始化操作。
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" init-method="Init" />
    </objects>
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using Spring.Core;
    using Spring.Context;
    using Spring.Context.Support;

    namespace ConsoleApplication1.SpringNet
    {
      public class HelloWorld
      {
        public HelloWorld()
        {
        }

        public void Init()
        {
          Console.WriteLine("Init...");
        }
      }

      public class Program
      {
        static void Main()
        {
          IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");

          object o = context.GetObject("HelloWorld");
          Console.WriteLine(o);
        }
      }
    }

    需要注意的是对于 Singleton 方式来说,初始化只会被执行一次,因为后续对象是直接从容器中拷贝引用而已。

    5. 设置对象属性

    除了在配置文件中提供构造参数外,我们还可以直接为对象属性赋值。
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using Spring.Core;
    using Spring.Context;
    using Spring.Context.Support;

    namespace ConsoleApplication1.SpringNet
    {
      public class HelloWorld
      {
        public HelloWorld()
        {
        }

        private string name;

        public string Name
        {
          get { return name; }
          set { name = value; }
        }

        public override string ToString()
        {
          return name;
        }
      }

      public class Program
      {
        static void Main()
        {
          IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");
          
          object o = context.GetObject("HelloWorld");
          Console.WriteLine(o);
        }
      }
    }
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
        <property name="Name" value="Tom" />
      </object>
    </objects>

    6. 设置类型参数

    上面的例子我们注入的数据都是基本类型,对于自定义类型我们需要做些声明。下面的例子中 HelloWorld 需要 2 个构造参数,分别是一个自定义类型和 Type。
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    using Spring.Core;
    using Spring.Context;
    using Spring.Context.Support;

    namespace ConsoleApplication1.SpringNet
    {
      public class MyData
      {
        public override string ToString()
        {
          return "MyData...";
        }
      }

      public class HelloWorld
      {
        private MyData data;

        public HelloWorld(MyData data, Type type)
        {
          this.data = data;
          Console.WriteLine(type);
        }

        public override string ToString()
        {
          return data.ToString();
        }
      }

      public class Program
      {
        static void Main()
        {
          IApplicationContext context = new XmlApplicationContext(@"Config\Spring.xml");

          object o = context.GetObject("HelloWorld");
          Console.WriteLine(o);
        }
      }
    }
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
        <constructor-arg name="data" ref="MyData" />
        <constructor-arg name="type" value="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
      </object>

      <object id="MyData" type="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
    </objects>

    一定要注意,注入一个对象和一个 Type 的不同之处。

    配置文件功能,将在后面做进一步介绍。

    [Spring.NET IoC] 之四:配置补充

     
    1. 别名
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" />
      <alias alias="HelloWorld2" name="HelloWorld"/>
    </objects>

    我们为 HelloWorld 创建了一个别名 HelloWorld2,我们同样可以通过 HelloWorld2 获取对象。请注意下面的测试代码输出结果。
    object o = context.GetObject("HelloWorld");
    object o2 = context.GetObject("HelloWorld2");
    Console.WriteLine(object.ReferenceEquals(o, o2)); // output: true

    2. 继承

    下面的例子中,我们为 HelloWorld 添加了一个 "parent" 声明,该申明表示 HelloWorld 继承 test 的配置属性,包括构造参数和属性设置,但不包括 "singleton" 等。当然继承的仅仅是配置信息,而不是类型。
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="test" type="ConsoleApplication1.SpringNet.Test, Learn.CUI" singleton="false">
        <constructor-arg name="s" value="abc..." />
      </object>
      
      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI" parent="test" />
    </objects>

    3. 内联

    对于下面的配置文件,我们还可以改成内联方式。
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
        <constructor-arg name="data" ref="MyData" />
      </object>

      <object id="MyData" type="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
    </objects>

    修改结果
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
        <constructor-arg name="data">
          <object type="ConsoleApplication1.SpringNet.MyData, Learn.CUI" />
        </constructor-arg>
      </object>

    </objects>

    4. 空值

    注意空值(null) 和空字符串("")不同。
    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
        <constructor-arg name="s">
          <null/>
        </constructor-arg>
      </object>
    </objects>

    [Spring.NET IoC] 之五:列表参数 

    我们可以在配置文件中向构造方法或者属性注入列表型参数,诸如 Array、ArrayList、Hashtable 等。

    1. IList

    在 .NET Framework 中实现 IList 的主要是 Array、ArrayList。

    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
        <constructor-arg name="list">
          <list>
            <value>1</value>
            <value>2</value>
            <value>3</value>
            <value>4</value>
          </list>
        </constructor-arg>
      </object>
    </objects>
    public class HelloWorld
    {
      public HelloWorld(IList list)
      {
        Console.WriteLine(list); // output: ArrayList
        foreach (object o in list)
          Console.WriteLine(o);
      }
    }


    我们会发现 Spring.NET IoC 缺省使用 ArrayList 来实现 IList 列表参数。

    2. IDictionary

    实现 IDictionary 的最常用类型是 Hashtable。

    <?xml version="1.0" encoding="utf-8"?>
    <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.net
             http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HelloWorld" type="ConsoleApplication1.SpringNet.HelloWorld, Learn.CUI">
        <constructor-arg name="dict">
          <dictionary>
            <entry key="1" value="a" />
            <entry key="2" value="b" />
            <entry key="3" value="c" />
            <entry key="4" value="d" />
          </dictionary>
        </constructor-arg>
      </object>
    </objects>
    public class HelloWorld
    {
      public HelloWorld(IDictionary dict)
      {
        Console.WriteLine(dict); // output:System.Collections.Specialized.HybridDictionary
        foreach (object o in dict.Keys)
        {
          Console.WriteLine("{0}={1}", o, dict[o]);
        }
      }
    }


    看看 System.Collections.Specialized.HybridDictionary 的MSDN说明

    在集合较小时,使用 ListDictionary 来实现 IDictionary,然后当集合变大时,切换到 Hashtable。
    建议将该类用于字典中的元素数量未知的情况。它利用了 ListDictionary 处理小集合时性能改善的优点,同时也可灵活地切换到处理较大集合时能力比 ListDictionary 更好的 Hashtable。
    如果集合的初始大小大于 ListDictionary 的最佳大小,那么集合立即存储在 Hashtable 中,以避免将元素从 ListDictionary 复制到 Hashtable 产生的系统开销。

  • 相关阅读:
    Java--环境变量(jdk、jre)配置
    Jsoup爬取数据设置代理IP
    数据库连接的莫名问题:create connection error
    springBoot使用过程的小感悟
    Activiti工作流引擎数据库表结构
    IDEA创建Activiti工作流开发
    Java开源爬虫框架WebCollector设置代理
    使用OkHttpClient爬取json数据
    雪中的杭州
    StringBuffer中的append方法
  • 原文地址:https://www.cnblogs.com/wangjei155/p/1499578.html
Copyright © 2011-2022 走看看