正 文

用AspectJ和Spring进行依赖项插入


www.7dspace.com  更新日期:2006-1-26 7:31:09  七度空间


  使用 Spring 进行依赖项插入

  在标准的 Spring 部署中,Spring 容器同时负责创建和配置核心应用程序对象(称为 bean)。因为容器既创建对象,又扮演代理的角色,所以对 Spring 容器来说,确定 bean 已经创建而且需要配置是件轻而易举的小事。通过查询应用程序的元模型,可以确定 bean 的依赖项,元模型通常是在 Spring 的配置文件中用 XML 表示的。

  满足 bean 的依赖项的对象是容器管理的其他 bean。容器充当这些 bean 的仓库,所以可以用名称查询它们(或者在需要的时候创建)。最后,容器用新 bean 的依赖项对其进行配置。这通常是通过 setter 插入完成的(调用新 bean 的 setter 方法,把依赖项作为参数传递进去),虽然 Spring 支持其他形式的插入,例如构造函数插入和查询方法插入(请参阅 参考资料 学习关于使用 Spring 进行依赖项插入的更多内容。)

  方面的依赖项插入

  像其他对象一样,方面可以从通过依赖项插入进行的配置中受益。在许多情况下,把方面实现为轻量级控制器 是良好的实践。在这种情况下,方面确定什么时候应当执行某些行为,但是会委托给协作器去执行实际的工作。例如,可以用异常处理策略对象配置异常处理方面。方面会探测出什么时候抛出了异常,并委托处理器对异常进行处理。清单 1 显示了基本的 RemoteException 处理方面:

清单 1. RemoteException 处理方面

public aspect RemoteExceptionHandling {
      private RemoteExceptionHandler exceptionHandler;
    
      public void setExceptionHandler(RemoteExceptionHandler aHandler) {
        this.exceptionHandler = aHandler;
      }
    
      pointcut remoteCall() : call(* *(..) throws RemoteException+);
    
      /**
       * Route exception to handler. RemoteException will still 
       * propagate to caller unless handler throws an alternate 
       * exception.
       */
      after() throwing(RemoteException ex) : remoteCall() {
        if (exceptionHandler != null)  
          exceptionHandler.onRemoteException(ex);
      }
    }

  现在我要用依赖项插入,用一个特殊的异常处理策略来配置我的方面。对于这个方面,我可以用标准的 Spring 方式,但是有一个警告。一般来说,Spring 既负责创建 bean,也负责配置 bean。但是,AspectJ 方面是由 AspectJ 运行时创建的。我需要 Spring 来配置 AspectJ 创建的方面。对于单体方面最常见的形式,例如上面的 RemoteExceptionHandling 方面,AspectJ 定义了一个 aspectOf() 方法,它返回方面的实例。我可以告诉 Spring 使用 aspectOf() 方法作为工厂方法,获得方面的实例。清单 2 显示了方面的 Spring 配置:

清单 2. 方面的 Spring 配置

  <beans>      
      <bean name="RemoteExceptionHandlingAspect"
        class="org.aspectprogrammer.dw.RemoteExceptionHandling"
        factory-method="aspectOf">
        <property name="exceptionHandler">
          <ref bean="RemoteExceptionHandler"/>
        </property>
      </bean> 
       
      <bean name="RemoteExceptionHandler" 
        class="org.aspectprogrammer.dw.DefaultRemoteExceptionHandler">
      </bean>
  </beans>

  我想确保我的方面在远程异常抛出之前得到配置。在示例代码中,我用 Spring 的 ApplicationContext 确保了这种情况,因为它会自动地预先实例化所有单体 bean。如果我使用普通的 BeanFactory,然后再调用 preInstantiateSingletons,也会实现同样的效果。

  域对象的依赖项插入

  配置单体方面就像在 Spring 容器中配置其他 bean 一样简单,但是对于拥有其他生命周期的方面来说,该怎么办呢?例如 perthis、pertarget 甚至 percflow 方面?生命周期与单体不同的方面实例,不能由 Spring 容器预先实例化;相反,它们是由 AspectJ 运行时根据方面声明创建的。迄今为止,代理 (Spring)已经知道了对象需要配置,因为它创建了对象。如果我想执行非单体方面的依赖项插入,就需要用不同的策略来确定需要配置的对象已经创建。

  非单体方面不是能够从外部配置受益的、在 Spring 容器的控制之外创建的惟一对象类型。例如,需要访问仓库、服务和工厂的域实体(请参阅 参考资料)也会从依赖项插入得到与容器管理的 bean 能得到的同样好处。回忆一下代理的四项职责:

    * 确定对象需要配置(通常因为对象刚刚创建)
    * 确定对象的依赖项
    * 发现满足这些依赖项的对象
    * 用对象的依赖项对它进行配置

  我仍然想用 Spring 来确定对象的依赖项,去发现满足这些依赖项的对象,并用对象的依赖项来配置对象。但是,需要另一种方法来确定对象需要配置。具体来说,我需要一个解决方案,针对那些在 Spring 的容器控制之外,在应用程序执行过程中的任意一点上创建的对象。

4页,页码:[1] [2] [3] [4] 

上一篇:PHP程序员的优化调试技术和技巧
下一篇:VC实现类似Excel文件夹式样的标签控制
标题:用AspectJ和Spring进行依赖项插入 作者:Adrian Colyer 来源:ibm
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐