Vincent.Chan‘s Blog

          常用鏈接

          統計

          積分與排名

          網站

          最新評論

          Webwork 2.2的Action是否使用Spring的prototype-獲取的性能對比

          1、引子:
          其實是ajoo的這篇“Nuts和Spring 1.2.6 效率對比”和“IoC容器的prototype性能測試 ”,他們在Javaeye上詳細討論了Spring的prototype的缺陷。
          Spring的prototype指的就是singleton="false"的bean,具體可以看Spring參考手冊“3.2.5. To singleton or not to singleton”介紹。

          2、Webwork 2.2的Spring結合問題:
          Webwork 2.2已經拋棄自己的IoC,默認使用Spring的IoC。
          上在OpenSymphony的官方Wiki,和jscud后來的幾篇文章中沒有特別提出prototype的問題。但是托他們的福,我們已經順利的使Spring和Webwork良好的協同工作起來了。
          可是而后的一些問題卻把prototype的問題搞得神秘起來……
          ajoo的測試中指出Spring的prototype性能很差,參見后面參考中的一篇文章和Javaeye的討論。
          而后又發現robbin在Javaeye的Wiki上面的“集成webwork和spring”中的最后注到:
          “注意:目前并不推薦使用Spring來管理Webwork Action,因為對于prototype類型的bean來說,Spring創建bean和調用bean的效率是很低的!更進一步信息請看IoC容器的prototype性能測試”
          這就使我們常用的Spring+Webwork2.2的連接中使用的prototype的問題被擺出來了。
          我現在的項目中使用了prototype的方式將Webwork Action使用Spring進行顯示的裝配,我擔心這個性能的問題會很嚴重,所以今天花了半天時間具體測試了一下。

          3、Prototype VS autowire的解釋:
          我不知道怎么命名兩種方式好,所以這里先做個解釋:
          spring的配置中Action會有個id,如:

          <bean id="someAction" class="com.tin.action.SomeAction" parent="basicActionWithAuthtication" singleton="false">
           
          <property name="someDAO">
            
          <ref bean="someDAO" />
           
          </property>
          </bean>

          我指的prototype方式就是在xwork中這樣配置:

          <action name="someAction" class="someAction">

          而autowire方式就是指在xwork中這樣配置:

          <action name="someAction" class="com.tin.action.SomeAction">

          看起來相同,但其實不同(我以前發過帖子,其中說這幾種方法都可,但是其實它們的機制是不同的。

          4、Portotye和autowire在XWork的SpringObjectFactory中是如何運作的:
          我們先看一下代碼,就能明白兩者的區別了:

          public Object buildBean(String beanName, Map extraContext) throws Exception {
           
          try {
                      
          return appContext.getBean(beanName);
                  }
           catch (NoSuchBeanDefinitionException e) {
                      Class beanClazz 
          = getClassInstance(beanName);
                      
          return buildBean(beanClazz, extraContext);
                  }

              }


              
          public Object buildBean(Class clazz, Map extraContext) throws Exception {
                  Object bean;

                  
          try {
                      bean 
          = autoWiringFactory.autowire(clazz, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
                  }
           catch (UnsatisfiedDependencyException e) {
                      
          // Fall back
                      bean = super.buildBean(clazz, extraContext);
                  }


                  bean 
          = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName());
                  
          // We don't need to call the init-method since one won't be registered.
                  bean = autoWiringFactory.applyBeanPostProcessorsAfterInitialization(bean, bean.getClass().getName());

                  
          return autoWireBean(bean, autoWiringFactory);
              }


              
          public Object autoWireBean(Object bean) {
                  
          return autoWireBean(bean, autoWiringFactory);
              }


          如果按照autowire配置會使用第二個buildBean方法,而prototype會使用第一個buildBean方法。

          5、我的測試,首先測試SpringObjectFactory的理論效率:

          public class testSpringObjectFactory extends TestCase {
              
          protected FileSystemXmlApplicationContext appContext;
              
          protected SpringObjectFactory sof = null;
              
          protected Map map = null;
              
          final String[] paths = {
                      
          "WebRoot/WEB-INF/applicationContext.xml",
                      
          "WebRoot/WEB-INF/spring-daos.xml",
                      
          "WebRoot/WEB-INF/spring-actions.xml"
                  }
          ;

              
          protected void setUp() throws Exception {
                  
          super.setUp();
                  appContext 
          = new FileSystemXmlApplicationContext(paths);

                  sof 
          = new SpringObjectFactory();
                  sof.setApplicationContext(appContext);
                  sof.setAutowireStrategy(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);

                  map 
          = new HashMap();
              }


              
          public void testSpringObjectFacotyWithAutowire() {
                  
          long begin = System.currentTimeMillis();

                  
          try {
                      
          for (int i = 0; i < 100000; i++{
                          sof.buildBean(
          "com.wqh.action.XinfangNewsAction", map);
                      }

                  }
           catch (Exception e) {
                      e.printStackTrace();
                  }


                  
          long end = System.currentTimeMillis();
                  System.out.println(
          "**************************Used time:" +
                      (begin 
          - end));
              }


              
          public void testSpringObjectFacotyWithPrototype() {
                  
          long begin = System.currentTimeMillis();

                  
          try {
                      
          for (int i = 0; i < 100000; i++{
                          sof.buildBean(
          "xinfangNewsAction", map);
                      }

                  }
           catch (Exception e) {
                      e.printStackTrace();
                  }


                  
          long end = System.currentTimeMillis();
                  System.out.println(
          "**************************Used time:" +
                      (begin 
          - end));
              }

              
              
          public void testSpringObjectFacotyWithSpringProxyableObjectFactory() {
                  sof 
          = new SpringProxyableObjectFactory();
                  sof.setApplicationContext(appContext);
                  sof.setAutowireStrategy(AutowireCapableBeanFactory.AUTOWIRE_BY_NAME);

                  
          long begin = System.currentTimeMillis();

                  
          try {
                      
          for (int i = 0; i < 100000; i++{
                          sof.buildBean(
          "com.wqh.action.XinfangNewsAction", map);
                      }

                  }
           catch (Exception e) {
                      e.printStackTrace();
                  }


                  
          long end = System.currentTimeMillis();
                  System.out.println(
          "**************************Used time:" +
                      (begin 
          - end));
              }

          }

           

          重要的是測試結果:
          **************************Used time:-16875
          **************************Used time:-80500
          **************************Used time:-12703(使用SpringProxyableObjectFactory()這個實現)

          prototype是autowire運行時間的4.77X倍,十分可觀。

          6、在實際的Web項目中的性能對比:
          我使用了我的一個小項目,就是反復調用一個action獲取一個頁面,其中有一個DAO注入。使用了JMeter進行了一個測試:2個線程,間隔0.5秒,循環50次,對比“據和報告中的”Throughput,單位/sec。
          使用autowire方式:Avg. 148.34(吞吐量越高越好)
          使用prototype方式:Avg. 138.5

          也就是說在實際應用中兩者也是有性能差距的,后者大約是前者性能的93%。
          具體代碼我不放出了,因為意義不大,大家也可以自己動手試驗一下。

          7、后續:
          如果理想測試下兩者性能差距4.7倍,實際性能差距在7%左右。這基本上讓我心里有點底了。
          但是使用autowire還是有trade off的。失去了Spring的顯示配置,也難使用Spring的AOP支持,這樣Spring的聲明性事務就不容易使用了,像Acegi這樣的安全框架也難以使用。所以這需要自己選擇了。
          但 是注意5中結果里面的SpringProxyableObjectFactory性能非常好,我看了下代碼,它將調用過的bean注冊到Spring的 BeanRegistry中,性能還是很不錯的,但是為什么快我還沒有仔細看,如何配置我也不太清楚,希望明白的朋友跟進講解。

          8、參考資源:
          Nuts和Spring 1.2.6 效率對比
          http://www.javaeye.com/pages/viewpage.action?pageId=786
          IoC容器的prototype性能測試
          http://forum.javaeye.com/viewtopic.php?t=17622&postdays=0&postorder=asc&start=0
          JavaEye的Wiki:集成webwork和spring
          http://www.javaeye.com/pages/viewpage.action?pageId=860
          WebWork - Spring官方Wiki
          http://www.opensymphony.com/webwork/wikidocs/Spring.html
          webwork2 + spring 結合的幾種方法的小結
          http://www.aygfsteel.com/scud/archive/2005/09/21/13667.html

          posted on 2006-02-14 23:30 Vincent.Chen 閱讀(615) 評論(0)  編輯  收藏 所屬分類: WebWork&Struts

          主站蜘蛛池模板: 金沙县| 获嘉县| 兴义市| 进贤县| 伊川县| 阳新县| 三江| 襄城县| 石家庄市| 宝鸡市| 武乡县| 平和县| 宜城市| 都匀市| 白朗县| 丰县| 泗水县| 信阳市| 新津县| 宜宾县| 永胜县| 遂宁市| 乡城县| 巴青县| 福贡县| 双桥区| 垦利县| 进贤县| 马尔康县| 奈曼旗| 贵州省| 葵青区| 宁阳县| 京山县| 犍为县| 汉阴县| 永定县| 古蔺县| 阿克| 辽中县| 麻城市|