[原創]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。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章