stone2083

          活用Srping AOP

          總有那么一些代碼,在測試環境下,是不能輕易被調用的。
          比如:
          1)發送系統任務郵件到客戶郵箱,可能一不小心,就把測試郵件發送給了真實客戶的郵箱里;
          2)調用跨公司的系統接口,而對方系統沒有測試環境,每調用一次接口,就會在對方系統產生垃圾數據;
          3)調用的代碼可能需要大量的cpu運算,占用大量的內存空間,消耗大量的資源;
          等等。。。

          為了解決這樣的需求,
          1)在代碼中,到處充斥著這樣的代碼:
          1 if(在測試環境下) {
          2     打印日志;
          3 else {
          4     調用真實的業務邏輯;
          5 }
          于是乎,需要到處維護這樣的代碼,一旦增加此類需求,就需要編寫同樣的代碼

          2)部分懶惰的程序員,連這樣的if...else...也不愿意寫,僅僅在注釋中說明下在測試環境中調用方法的危害性。
          于是,在測試階段,一旦和測試部門溝通不足,導致代碼還是經常被調用到,如果是在作壓力,性能測試,那么危害性可想而已。
          曾發生過,壓力測試某個功能,結果把大量的測試郵件,發送給了客戶,影響很差。


          那么,如何解決這樣的需求場景呢?
          沒錯,采用proxy模式,可以搞定。考慮到現在很多企業都使用Spring作為IOC容器,本文就簡單介紹,如何采用spring aop來解決問題。

          以發送郵件的需求作為虛擬場景。
          現在有個Service,專門負責郵件的發送。
          1. MyService.java
          1 public class MyService {
          2     public void sendMailSafely() {
          3     System.out.println("send mail successfully.");
          4     }
          5 }

          如果這個sendMailSafely被客戶端調用,那么毫無疑問,郵件不管任何環境下,都會被成功發送。
          需要有個方法攔截器,對這個方法做攔截。
          2. MyInterceptor.java
           1 public class MyInterceptor implements MethodInterceptor {
           2 
           3     private boolean isProduction = false;
           4 
           5     @Override
           6     public Object invoke(MethodInvocation invocation) throws Throwable {
           7     if (!isProduction) {
           8         System.out.println("is production environment.do nothing");
           9         return null;
          10     }
          11     return invocation.proceed();
          12     }
          13 
          14     public void setProduction(boolean isProduction) {
          15     this.isProduction = isProduction;
          16     }
          17 
          18 }
          這個攔截器,根據配置文件的參數isProduction判斷是否在正式環境,如果是在測試環境,對方法做攔截,僅僅打印log,不真實調用業務邏輯。

          如何讓sendMailSafely()方法被此攔截器做攔截,所以通過spring配置文件,配置一個advisor,通知對以Safely結尾的方法做攔截
          3.  application.xml
           1 <bean id="safetyAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" scope="singleton">
           2     <property name="advice">
           3       <ref local="myInterceptor" />
           4     </property>
           5     <property name="patterns">
           6       <list>
           7         <value>.*Safely</value>
           8       </list>
           9     </property>
          10   </bean>

          附上application.xml的全部內容
           1 <beans default-autowire="byName">
           2 
           3   <!-- service實例 -->
           4   <bean id="myService" class="cn.zeroall.javalab.aop.MyService" scope="singleton" />
           5 
           6   <!-- 方法攔截器 -->
           7   <bean id="myInterceptor" class="cn.zeroall.javalab.aop.MyInterceptor" scope="singleton">
           8     <property name="production" value="false" />
           9   </bean>
          10 
          11   <!-- 通知者 -->
          12   <bean id="safetyAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" scope="singleton">
          13     <property name="advice">
          14       <ref local="myInterceptor" />
          15     </property>
          16     <property name="patterns">
          17       <list>
          18         <value>.*Safely</value>
          19       </list>
          20     </property>
          21   </bean>
          22 
          23   <!-- myService代理類 -->
          24   <bean id="safetyService" class="org.springframework.aop.framework.ProxyFactoryBean" scope="singleton">
          25     <property name="interceptorNames">
          26       <list>
          27         <value>safetyAdvisor</value>
          28       </list>
          29     </property>
          30     <property name="targetName" value="myService" />
          31   </bean>
          32 
          33 </beans>


          寫一個Client類來做演示。
          4. Client.java
           1 public class Client {
           2 
           3     private ApplicationContext ctx = new ClassPathXmlApplicationContext(
           4         "cn/zeroall/javalab/aop/application.xml");;
           5 
           6     public static void main(String[] args) {
           7         Client c = new Client();
           8         c.sendMail();
           9         c.sendMailSafety();
          10     }
          11 
          12     public void sendMail() {
          13         MyService myService = (MyService) ctx.getBean("myService");
          14         myService.sendMailSafely();
          15     }
          16 
          17     public void sendMailSafety() {
          18         MyService myService = (MyService) ctx.getBean("safetyService");
          19         myService.sendMailSafely();
          20     }
          21 
          22 }
          大家可以看看最終輸出的結果內容。

          一直來,我都不會濫用AOP,尤其反感使用AOP來寫業務邏輯內容,但是對于這類非業務邏輯需求,采用spring aop技術那是剛剛好啊。

          最后,附上全部代碼文件(使用maven構建)。
          演示代碼

          posted on 2008-06-01 15:21 stone2083 閱讀(507) 評論(0)  編輯  收藏 所屬分類: java

          主站蜘蛛池模板: 孝义市| 吴江市| 兴文县| 塔城市| 察隅县| 永清县| 恩施市| 拜泉县| 金乡县| 林甸县| 巴东县| 金沙县| 香格里拉县| 衢州市| 扬中市| 公主岭市| 赣州市| 长沙市| 瑞昌市| 图们市| 双辽市| 长子县| 凤翔县| 焦作市| 昌黎县| 高雄市| 资兴市| 繁峙县| 盈江县| 枣庄市| 西乡县| 福建省| 灌阳县| 锡林郭勒盟| 都江堰市| 安图县| 顺昌县| 永丰县| 合肥市| 枞阳县| 广德县|