• 使用方法的返回值进行注入


    本节要讲的第三个类是MethodInvokingFactoryObject。MethodInvokingFactoryObject允许使用任意方法的返回值进行注入。

    MethodInvokingFactoryObject类可以处理实例方法和静态方法。此外,Spring.NET中另有一种处理对象初始化的机制(参考4.5.1.1,IInitializingObject接口和init-method属性)也可以用来进行(初始化)方法的调用,但是用这种机制调用方法的目的只是进行初始化工作,并且不允许向方法中传递任何参数,调用的时机也被限制在对象被容器创建时。MethodInvokingFactoryObject类则允许在任意时刻调用任意对象的任意方法(或者任意类的静态方法)。

    在下面的例子中,使用MethodInvokingFactoryObject类强制在myService对象创建之前调用一个静态方法。

    <object id="force-init"
    type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
    <property name="TargetMethod" value="Initialize">
    <property name="TargetType" value="ExampleNamespace.ExampleInitializerClass, ExampleAssembly">
    </object>

    <object id="myService" type="MyService" depends-on="force-init"/>

    (按:原文中上面的例子似有错误,此处已做修正;具体可参考英文文档)

    注意对象定义myService的depends-on属性引用了一个名为force-init的MethodInvokingFactoryObject对象,该引用会使对象force-init在myService之前初始化(并且调用force-init的目标类型上的目标方法。注意,若要使这个配置正常工作,myService对象必须以singleton模式操作(按:否则myService对象只会在请求时创建,而此时force-init已经被容器预先创建了,也就失去了depends-on的意义)——这也是默认的对象布署模式,参见下一章)。

    MethodInvokingFactoryObject类也可用于访问工厂方法(按:当在代码中通过名称"force-init"从容器中获取对象时,如果其目标方法有返回值,那么获得的对象就是目标方法的返回值;如果目标方法返回null,那么获得对象的类型则是System.Reflecton.Missing),一般情况下,工厂方法都是以singleton模式操作的。如果MethodInvokingFactoryObject对象为singleton模式,那么在它所有属性被设置后(按:应该是设置了足够的属性后,即TargetType和TargetMethod),目标方法会立即被调用并将返回值存入缓存以备用。随后,如果容器向此工厂请求对象,那么返回的将是缓存中的值。MethodInvokingFactoryObject对象的singleton属性可以设置为false,此时每次请求对象都会去调用目标方法(返回值不会被缓存)。

    在MethodInvokingFactoryObject的对象定义中,用TargetMethod和TargetType属性指定目标静态方法名和方法所在的类型全名;而用TargetMethod和TargetObject属性来指定目标实例方法名和方法所在对象的引用。

    目标方法的参数可以通过两种方式来设置(这两种方式可混合使用)。第一种是通过Arguments属性来指定参数列表。注意列表中项的顺序是很重要的——必须和方法签名中的参数列表在次序上完全一致,且类型兼容,如下例:

    <object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
      <property name="TargetType" value="Whatever.MyClassFactory, MyAssembly"/>
      <property name="TargetMethod" value="GetInstance"/>
      
      <!-- the ordering of arguments is significant -->
      <property name="Arguments">
        <list>
    
          <value>1st</value>
          <value>2nd</value>
          <value>and 3rd arguments</value>
          <!-- automatic Type-conversion will be performed prior to invoking the method -->
    
        </list>
      </property>
    </object>

    第二种方式是通过NamedArguments属性配置一系列键/值对,其中键名对应参数名(文本类型),值对应参数值(可以是任意对象)。参数名是大小写不敏感的,并且顺序(当然)是不重要的(因为词典类型本身就没有顺序)。见下面的例子:

    <object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
      <property name="TargetObject">
        <object type="Whatever.MyClassFactory, MyAssembly"/>
      </property>
      <property name="TargetMethod" value="Execute"/>
      
      <!-- the ordering of named arguments is not significant -->
    
      <property name="NamedArguments">
        <dictionary>
          <entry key="argumentName"><value>1st</value></entry>
          <entry key="finalArgumentName"><value>and 3rd arguments</value></entry>
    
          <entry key="anotherArgumentName"><value>2nd</value></entry>
        </dictionary>
      </property>
    </object>

    下面使用MethodInvokingFactoryObject来调用一个实例方法:

    <object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" />
    
    <object id="myObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
      <property name="TargetObject" ref="myMethodObject"/>
      <property name="TargetMethod" value="Execute"/>
    </object>

    上例中的目标对象也可以是匿名的内联对象定义...如果对象的方法不会在工厂对象之外调用,那么最好通过内联对象定义将目标方法限制在工厂对象内部。

    最后要注意,如果使用MethodInvokingFactoryObject来调用一个有变长参数列表的方法,必须使用list来按顺序定义要传递的参数值。请看下面的例子,其中CreateObject方法的参数arguments是用C#关键字params来定义的;随后是相应的XML配置:

    [C#]
    public class MyClassFactory
    {
        public object CreateObject(Type objectType, params string[] arguments)
        {
            return ... // implementation elided for clarity...
        }
    }
    <object id="myMethodObject" type="Whatever.MyClassFactory, MyAssembly" />
    				
    <object id="paramsMethodObject" type="Spring.Objects.Factory.Config.MethodInvokingFactoryObject, Spring.Core">
      <property name="TargetObject" ref="myMethodObject"/>
      <property name="TargetMethod" value="CreateObject"/>
      <property name="Arguments">
        <list>
    
          <value>System.String</value>
          <!-- here is the 'params string[] arguments' -->
          <list>
            <value>1st</value>
            <value>2nd</value>
    
          </list>
        </list>
    </object>
  • 相关阅读:
    Spring 学习十五 AOP
    Spring 学习十四 Spring security安全
    博客文格式优化
    作为一名软件测试工程师,需要具备哪些能力
    单元测试工程师需要具备的任职资格
    初识安全测试(一)
    压力测试工具JMeter入门教程
    Jmeter的优点是什么?除了轻量级,它和LoadRunner有什么本质区别
    初识Jmeter(一)
    初识Selenium(四)
  • 原文地址:https://www.cnblogs.com/chenzhao/p/2215309.html
Copyright © 2020-2023  润新知