[原创]Spring: A Developer's Notebook笔记和小结(17)

/**
作者:Willpower
来源:Rifoo Technology(
http://www.rifoo.com
时间:2006-03-21
备注:转载请保留以上声明
**/

本节我们主要讲解autoproxy的概念。

到目前为止,我们已经能够明确的手工去创建每一个proxy对象。然而Spring也提供了一种可能自动创建一个proxy对象的能力,或者简称autoproxy。autoproxy的目标是应用一些方法相同的特征。在本节的实验中,我们将使用一个autoproxy,将配置代码(profiling code)加到应用中的所有类中去。

Spring 中有两种方法可以让我们去进行autoproxy:

1 指定一个配置(configuration)并将它应用到named beans context中。

2 使用源码级的元数据(source-level metadata),该功能是JAVA 5的JDKK引入的,但是也可以通过Apache Commons annotations来使用。

在本例中,我们使用第一种方式。和前面一样,我们首先需要一些advice对象。下面的代码演示了around advice,它会在Spring进入一个方法之前和之后都打印相关配置(profiling)语句。

Example 6-7. ProfilingInterceptory.java
public class ProfilingInterceptor implements MethodInterceptor{
  public Object invoke(MethodInvocation methodInvocation)
      throws Throwable {
    long start = System.currentTimeMillis( );
    Object results = methodInvocation.proceed( );
    long end = System.currentTimeMillis( );
    System.out.println("Method: " +
      methodInvocation.getMethod( ).getName( ) + " took " +
      (end - start) + " ms.");
    return results;
  }
}


接着,我们配置它。这里不要指定一个唯一的目标对象,而使用正则表达式来指定模糊的目标对象。Spring会应用这个advice来匹配所有bean。下面的代码演示了指定autoproxy,advice和target。

Example 6-8. RentABike-servlet.xml
<bean name="profilerAround"
  class="com.springbook.interceptors.ProfilingInterceptor"/>

<bean name="profilingAutoProxy" class="
org.springframework.aop.framework.autoproxy.
BeanNameAutoProxyCreator
">
   
  <property name="beanNames"><value>rentaBike*</value></property>
  <property name="interceptorNames">
    <list>
      <value>profilerAround</value>
    </list>
  </property>
</bean>


现在,当我们在std.out控制台上运行应用程序时,我们能够看到应用程序程序告诉什么时候进入或离开了一个指定的方法,这个方法被执行了多少时间也可以看到。

Example 6-9. Standard out from running application
Entered toString
Method: toString took 0 ms.
Entered isSingleton
Method: isSingleton took 0 ms.
Entered getObject
Method: getObject took 0 ms.
Entered getObject
Method: getObject took 0 ms.
Entered getObject
Method: getObject took 0 ms.
Entered getObject
Method: getObject took 0 ms.
Entered getObject
Method: getObject took 0 ms.
Entered getObject
Method: getObject took 0 ms.
Entered saveBike
Method: saveBike took 31 ms.
Entered getBike
Method: getBike took 78 ms.
Entered deleteBike
Method: deleteBike took 62 ms.
Entered getBikes
Method: getBikes took 47 ms.


总结:
本例和以前章节的例子有两个主要的不同地方:
1 我们可以针对多个bean进行匹配操作
2 我们使用了一种不同类型的advice

下面我们详细分析:
首先看看拦截器本身。我们注意到,在invoke方法中MethodInterceptor advice做了很多工作,调用methodInvocation.proceed( )来完成更多任务。这个方法调用拦截器链中的下一个拦截器,或者如果是最后一个拦截器的话,则调用它的target方法。该操作有如下灵活性和好处:

1 我们可以在proceed()方法之前做很多工作,比如缓存我们方法的起始时间等,那段代码将在target方法执行之前执行。

2 我们可以在proceed()方法之后(但在它返回之前)做很多工作。那段代码将在target方法执行之后执行。

3 我们也可以决定不调用proceed()方法,那么target方法将不会被执行。

4 我们的代码可以引发一个异常,来改变控制流程。在我们的异常中,我们可以决定是否去调用proceed()方法。

另外,这种类型的advice和其他advice工作方法一样。那么我们应该使用哪一种advice呢?Spring的创始人Rod Johnson建议我们使用最弱类型的advice(the weakest type of advice )来为我们工作。

本例区分与其他以前的例子还有另一个不同的地方:目标对象(target)。我们可以代理多个target。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章