<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Tin's Blog

    You are coming a long way, baby~Thinking, feeling, memory...

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      128 隨筆 :: 0 文章 :: 221 評論 :: 0 Trackbacks

    本文在060216進(jìn)行了修改,因?yàn)榘l(fā)現(xiàn)了測試中的錯誤!注意5.5和7的內(nèi)容。

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

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

    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">

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

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

    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));
        }

    }

     

    重要的是測試結(jié)果:
    **************************Used time:-16875
    **************************Used time:-80500
    **************************Used time:-12703(使用SpringProxyableObjectFactory()這個實(shí)現(xiàn))

    prototype是autowire運(yùn)行時間的4.77X倍,十分可觀。

    5.5 巨大的反差,原來是我搞錯了配置,發(fā)現(xiàn)了幕后黑手:
    第二天,我又重新運(yùn)行了5里面的測試。但是結(jié)果令人吃驚,運(yùn)行了十多次,結(jié)果于昨天反差巨大,prototype方式獲得的bean反而性能最快!
    摘要兩次測量結(jié)果
    **************************Autowire Used time:-17578
    **************************Prototype Used time:-7609
    **************************Proxy Used time:-13063
    -----------------------------------------------
    **************************Autowire Used time:-17047
    **************************Prototype Used time:-7609
    **************************Proxy Used time:-12797

    這是為什么呢?我百思不得其解,問題出在哪里呢?后來經(jīng)過跟蹤svn里面的提交紀(jì)錄。我發(fā)現(xiàn),我在昨天測試以后,把spring配置文件中的<beans default-autowire="autodetect">變成了<beans>。也就是沒有打開自動檢測的autowire!
    而后就真相大白了。我有配置上default-autowire="autodetect"進(jìn)行測試,結(jié)果:
    **************************Autowire Used time:-16937
    **************************Prototype Used time:-79750
    **************************Proxy Used time:-12578

    這和昨天的測試結(jié)果完全相同。也就是說我昨天寫的4.77x的結(jié)果其實(shí)沒有實(shí)際意義。倒是說明了Spring和Webwork集成的文章上面說的default-autowire="autodetect"是很壞的實(shí)踐,即失去了name的靈活性也帶來了巨大的性能損失。
    而如果使用默認(rèn)的Spring autowire配置下,prototype的性能已經(jīng)很好了,實(shí)際上它工作起來應(yīng)該是最快的。

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

    也就是說在實(shí)際應(yīng)用中兩者也是有性能差距的,后者大約是前者性能的93%。
    具體代碼我不放出了,因?yàn)橐饬x不大,大家也可以自己動手試驗(yàn)一下。
    補(bǔ)充說明:
    首先注意這個測試是在default-autowire="autodetect"下進(jìn)行的。
    測試的這個Action其實(shí)是一個空Action,它沒有調(diào)用service和DAO,只是直接return SUCCESS,然后dispatcher到一個靜態(tài)內(nèi)容的jsp頁面。我的本意是為了能夠在獲取Action占據(jù)的時間比例比較高的情況下分析性能區(qū)別。但是實(shí)際上卻間接的夸大了在真正的實(shí)際應(yīng)用中的性能差距。實(shí)際應(yīng)用中如果加上service、DAO等邏輯的執(zhí)行時間、模板View的渲染時間還有廣域網(wǎng)上的網(wǎng)絡(luò)傳輸時間,那么獲取Action實(shí)例的時間差距可能就微乎其微了。

    7、后續(xù):
    經(jīng)過今天的思考,可以說完全改變了想法,重新匯總一下:
    a、在不使用default-autowire="autodetect"時,Webwork 2.2的xwork中的action class使用spring的bean id配置的理論性能最好。而且,我認(rèn)為如果不是為了追求配置上的簡單,嚴(yán)重推薦關(guān)閉spring的default-autowire。
    b、在使用default-autowire="autodetect、name、class"時,需要考慮你的需求。如果不使用Spring AOP提供的功能則在Webwork 2.2的xwork中的action class使用class全名比較好。如果使用Spring AOP的功能,則還是使用bean id。
    c、在Spring中是否使用default-autowire是個需要慎重考慮的問題。autowire如果打開,命名會受到限制(class則更不推薦,受限更大,參考相關(guān)文檔),它所帶來的配置簡化我認(rèn)為只算是小小的語法糖果,背后卻是吃掉它所埋下的隱患。
    d、6中的測試還是有些說明意義的。7%的性能差距是在使用了default-autowire的方式下得出的,其中測試的那個action其實(shí)沒有執(zhí)行什么邏輯,而是一個直接dispatcher到success view的action,如果有商業(yè)邏輯包裝,則性能差據(jù)估計(jì)會更小。因?yàn)閷?shí)際上Action的執(zhí)行過程、service、DAO等邏輯的執(zhí)行過程和模板View的渲染過程(網(wǎng)絡(luò)延遲)才是耗時大戶。所以,關(guān)于性能應(yīng)該下的結(jié)論是,prototype與否,在實(shí)際應(yīng)用中性能差距是很小的,基本可以忽略不計(jì)。我們討論的更多是編碼的更好的實(shí)踐。
    e、autowire不使用Spring AOP相對還是trade off,因?yàn)殡m然配置簡單一點(diǎn),但是對于使用Spring的聲明性事務(wù)等內(nèi)容會帶來麻煩。雖然XML不那么好,但是顯示配置帶來的好處還是很多的。
    f、謝謝robbin的提示。關(guān)于事務(wù)我也是無奈,放棄Action事務(wù)后難道給DAO多封裝一層事務(wù)?如何沒有事務(wù)依然使用HibernateDAOSurpport?Acegi的確不適合Web,使用WW的Inteceptor可以實(shí)現(xiàn)更舒適的解決方案。
    g、SpringProxyableObjectFactory的問題……使用上難道只能改代碼?找了半天沒有這個東西的介紹。看來還是需要看看代碼。不過發(fā)現(xiàn)現(xiàn)在Webwork和Xwork的代碼又變動了很多……
    h、我的測試是在Webwork2.2+Spring 1.2.6環(huán)境下測試的


    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 結(jié)合的幾種方法的小結(jié)
    http://m.tkk7.com/scud/archive/2005/09/21/13667.html
    我為什么不推薦對Action進(jìn)行事務(wù)控制
    http://www.javaeye.com/pages/viewpage.action?pageId=1205
    我為什么不推薦使用Acegi
    http://www.javaeye.com/pages/viewpage.action?pageId=1199

    posted on 2006-02-14 21:48 Tin 閱讀(2403) 評論(0)  編輯  收藏 所屬分類: Webwork相關(guān)Spring相關(guān)
    主站蜘蛛池模板: 亚洲av鲁丝一区二区三区| 日韩精品免费视频| 亚洲一级毛片免费在线观看| 亚洲免费在线观看| 亚洲综合久久精品无码色欲| 69xx免费观看视频| 亚洲爆乳大丰满无码专区| 成年网站免费视频A在线双飞| 亚洲喷奶水中文字幕电影| 久久久精品2019免费观看 | 在线天堂免费观看.WWW| 黄页免费视频播放在线播放| 日本高清免费不卡视频| 亚洲熟妇AV乱码在线观看| 亚洲精品无码永久中文字幕| 国产午夜精品理论片免费观看| 国产偷国产偷亚洲高清日韩| 永久免费观看黄网站| 亚洲国产模特在线播放| 国产亚洲美女精品久久久2020| 野花高清在线观看免费完整版中文 | 欧洲乱码伦视频免费国产| 亚洲精品线路一在线观看| 成人午夜免费福利视频| 久久久WWW成人免费精品| 伊人亚洲综合青草青草久热| 国产香蕉九九久久精品免费 | 毛片免费在线观看网站| 天黑黑影院在线观看视频高清免费 | 日本二区免费一片黄2019| 99爱免费观看视频在线| 亚洲一区二区三区91| 最近中文字幕无免费视频 | 亚洲高清免费视频| 边摸边脱吃奶边高潮视频免费| 亚洲熟妇无码久久精品| 国产亚洲一区二区手机在线观看| 四虎影视永久免费观看| 成年女性特黄午夜视频免费看| 最近中文字幕免费mv在线视频| 中文字幕在线视频免费|