Spring.NET学习笔记10——方法的注入(基础篇)

多数用户都会将容器中的大部分对象布署为singleton模式。当一个singleton对象需要和另一个singleton对象协作,或者一个非singleton对象需要和另一个非singleson对象协作时,Spring.NET都能很好的处理它们的依赖关系。但是,如果对象的生存周期不同,就可能会产生问题。例如,假设一个singleton对象A要使用一个非singleton(原型)对象B,A中的每个方法都会用到B的新实例。由于A是singleton对象,容器只有会创建它一次,也就是说只有一次给A的属性赋值的机会,所以不可能在每次A需要的时候都给它注入一个新的B。

有一种解决的办法有点违背控制反转原则:类A可以通过实现IObjectFactoryAware接口来获取容器的引用,并调用GetObject("B")在每次需要的时候从容器中请求一个(新的)对象B。但这并不是一个很好的解决方案,因为客户代码此时必须要和Spring.NET发生紧耦合。

通过方法注入,我们可以用更优雅的方式解决类似的问题。(摘自Spring.NET中文手册)

  一、查询方法注入

  Spring.NET可以动态覆盖对象的抽象方法或虚方法,并且可以在容器内查找已命名对象,查询方法注入就利用了这些功能。个人感觉查询方法注入类似抽象工厂,为之不同的是,可以不用写抽象的实现代码,通过配置文件动态的切换组件
  在lookup-method节点配置name和object属性

  实现代码如下:

  1.       <!--查询方法-->
  2.       <object id="personDao" type="SpringNet_MethodDi.PersonDao, SpringNet_MethodDi" singleton="false"/>
  3.       <object id="objectFactory" type="SpringNet_MethodDi.ObjectFactory, SpringNet_MethodDi">
  4.         <lookup-method name="CreatePersonDao" object="personDao"/>
  5.       </object>
复制代码

LookupMethod

  1.     //注意,可以直接在配置中定义这个类的对象
  2.     public abstract class ObjectFactory 
  3.     {
  4.         //或者可以是一个虚方法   
  5.         public abstract PersonDao CreatePersonDao();   
  6.     }
  7.     public class PersonDao
  8.     {
  9.         public void Save()
  10.         {
  11.             Console.WriteLine("保存数据");
  12.         }
  13.     }
复制代码

  二、替换任意方法

  替换任意方法在项目中使用的很少,实现方法也比较复杂。至于Spring.NET为什么使用替换任意方法,我还不是很清楚,如果有知道使用场景的朋友可以给我留言。我个人认为其用途是:实现非派生类方法的重写或在IoC框架中简易的AOP拦截(这一点又不确定,以后我会写AOP方面的博客)。

  首先继承IMethodReplacer接口并实现Implement方法,object[] arguments为传入的参数。其次在replaced-method节点配置name和replacer属性,和增加arg-type节点且配置返回类型match属性

  代码如下:

  1.       <!--替换方法-->
  2.       <object id="userDao" type="SpringNet_MethodDi.UserDao, SpringNet_MethodDi">
  3.         <replaced-method name="GetValue" replacer="replaceValue">
  4.           <arg-type match="String"/>
  5.         </replaced-method>
  6.       </object>
  7.       <object id="replaceValue" type="SpringNet_MethodDi.ReplaceValue, SpringNet_MethodDi"/>
复制代码

ReplacedMethod

  1.     public class UserDao
  2.     {
  3.         //虚方法
  4.         public virtual string GetValue(string input)
  5.         {
  6.             return null;
  7.         }
  8.     }
  9.     //实现IMethodReplacer接口
  10.     public class ReplaceValue : IMethodReplacer
  11.     {
  12.         public object Implement(object target, MethodInfo method, object[] arguments)
  13.         {
  14.             string value = (string)arguments[0];
  15.             return "获取到:" + value;
  16.         }
  17.     }
复制代码三、事件注入

  在Spring.NET的IoC框架中,除了提供方法注入以外,还提供事件的注入。通过事件的注入,可以使架构体系的耦合降到最低。(参考 clingingboy的 Spring.NET学习笔记(3)-注册事件注入)

  在listener节点处配置event和method属性指明事件名和绑定的方法,并增加ref节点设置object属性来指明调用哪个IoC容器对象。

  实现代码:
  1.       <!--事件注入-->
  2.       <object id="men" type="SpringNet_MethodDi.Men, SpringNet_MethodDi">
  3.         <listener event="OpenTheDoor" method="OpenThisDoor">
  4.           <ref object="door"/>
  5.         </listener>
  6.       </object>         
  7.       <object id="door" type="SpringNet_MethodDi.Door, SpringNet_MethodDi" />
复制代码
Listener
  1.     //先定义一个委托
  2.     public delegate string OpenHandler(string arg);

  3.     public class Door
  4.     {
  5.         public event OpenHandler OpenTheDoor;

  6.         public void OnOpen(string arg)
  7.         {
  8.             //调用事件
  9.             if (OpenTheDoor != null)
  10.             {
  11.                 Console.WriteLine(OpenTheDoor(arg));
  12.             }
  13.         }
  14.     }

  15.     public class Men
  16.     {
  17.         public string OpenThisDoor(string arg)
  18.         {
  19.             return "参数是:" + arg;
  20.         }
  21.     }
复制代码
调用部分代码:

Program
  1. class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             IApplicationContext ctx = ContextRegistry.GetContext();

  6.             Console.WriteLine("查询方法");
  7.             ObjectFactory factory = (ObjectFactory)ctx.GetObject("objectFactory");
  8.             factory.CreatePersonDao().Save();
  9.             Console.WriteLine();

  10.             Console.WriteLine("替换方法");
  11.             UserDao dao = (UserDao)ctx.GetObject("userDao");
  12.             Console.WriteLine(dao.GetValue("Liu Dong"));
  13.             Console.WriteLine();

  14.             Console.WriteLine("事件注册");
  15.             Door door = (Door)ctx.GetObject("door");
  16.             door.OnOpen("Opening!");
  17.             Console.WriteLine();

  18.             Console.ReadLine();
  19.         }
  20.     }
复制代码
输入效果:

posted @ 2011-03-26 20:57  似水流年-johnhuo  阅读(164)  评论(0编辑  收藏  举报