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

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

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

    邊城愚人

    如果我不在邊城,我一定是在前往邊城的路上。

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      31 隨筆 :: 0 文章 :: 96 評論 :: 0 Trackbacks
    ??? ??? 本文通過一個“Hello World”級別的橫切性功能介紹Spring1.XAOP的使用,并結合Spring的經典的聲明式事務管理給出Spring AOP配置中的經典方案。在Spring2出來以后,Spring1.XAOP使用方式已經“不合時宜”了,因此如果你是在新項目中采用Spring AOP,建議使用Spring2中的AOP使用方式。關于Spring2.XAOP的使用,參考該文的姊妹文章Spring2.XAOP的使用

    ??? ??? 一提到AOP的應用,人們就會本能地提起日志功能,它就像一門語言的“Hello World”一樣被人們無數次提起。也許有人會疑問除了“不實用”的日志功能,AOP還能做些什么?可能在很多時候我們并不需要自己實現一個AOP功能,尤其是在擁有了很多優秀的AOP應用框架來解決通用的橫切性問題的情況下(比如Spring的事務管理、比如Acegi的安全管理、比如WebWork的攔截功能)。但問題總是層出不窮的,總會有些問題可能需要我們自己AOP一下。

    ??? ??? 在月言月,進入到該文的主題(寫完上面的一段使我想起俞平伯,那老頭很多文章的前幾段總是些不知所以的文字,直到“ 在月言月”一出,方進入文章主題;在看完文章后回頭一瞧,和主題相關的文字竟不到文章的半數!)。這個Sample要實現的AOP功能是最簡單的日志功能,在調用每個Service方法之前輸出被調用方法的簡單信息。

    ??? ??? 我們知道,AspectPointcutAdvice(如果您不知道的話,需要看一看Spring文檔了)。在Spring1.X中,不能以AspectJ的語法書寫復雜的切入點表達式(這是因為Spring1.X中的切入點是Java類)。Spring1.X可以使用正則表達式切入點以聲明的方式來簡化編程。這里假定要求對Service層中所有Service方法在調用之前輸出和方法相關的信息。切入點聲明如下:


    <bean?id="businessServicePointcut"?class="org.springframework.aop.support.JdkRegexpMethodPointcut">

    <property?name="patterns">

    <value>*</value>

    </property>

    </bean>

    ??? ??? 應該說明的是,在不使用通知器自動代理的情況下,聲明的切入點的作用域實在小的可憐,它不過是方法級別的。我覺得這也是Spring1.X中很不友好的一點,通過ProxyFactoryBean代理的方式實現AOP,需要對每個應用了AOP特性的Bean都做代理,即便是在Bean繼承的情況下也不友好。

    ??? ??? 下面要創建一個超簡單的Before通知:


    public?class?LogAdvice?implements?MethodBeforeAdvice{

    public?void?before(Method?arg0,?Object[]?arg1,?Object?arg2)?throws?Throwable?{

    //no?content

    }

    }

    ??? ??? 關于通知和切面的配置如下:

    <bean?id="logAdvice"?class="hibernatesample.service.util.LogAdvice"></bean>

    <bean?id="logAspect"?class="org.springframework.aop.support.DefaultPointcutAdvisor">

    <property?name="pointcut"?ref="businessServicePointcut"></property>

    <property?name="advice"?ref="logAdvice"></property>

    </bean>

    ??? ??? spring1.X中,AdvisorAspect的同義詞,這是spring1.X獨有的。坦率的說,我覺得這個詞真不應該出現,它會給AOP初學者造成很大的困惑,尤其是對AspectJ不了解的情況下。在spring1.X中,我們并不需要自己編寫一個Advisor,只需要使用Spring提供的Advisor封裝切入點和通知就行了。如果你不使用通知器自動代理并且要通知作用的類的所有方法,Advisor甚至是不需要的。好了,上面就是我們自定義的一個日志切面,我們還要加一個切面--經典的對于Service必不可少的事務切面。配置文件如下:


    <bean?id="transactionManager"

    class
    ="org.springframework.orm.hibernate3.HibernateTransactionManager">

    <property?name="sessionFactory">

    <ref?bean="sessionFactory"?/>

    </property>

    </bean>

    <bean?id="transactionInterceptor"?class="org.springframework.transaction.interceptor.TransactionInterceptor">

    <property?name="transactionManager"><ref?bean="transactionManager"/></property>

    <property?name="transactionAttributes">

    <props>

    <prop?key="get*">PROPAGATION_REQUIRED,readOnly</prop>

    <prop?key="*">PROPAGATION_REQUIRED</prop>

    </props>

    </property>

    </bean>

    ??? ???
    ??? ??? 你也看到了,transactionInterceptor是個攔截器,它只是對方法級別上做攔截.將transactionInterceptor和logAspect以ProxyFactoryBean方式作用到
    Service上,配置文件如下:

    <bean?id="accountServiceTarget"?class="hibernatesample.service.impl.AccountServiceImpl">

    <property?name="accountDAO"?ref="accountDAO"></property>

    </bean>


    <bean?id="accountService"?class="org.springframework.aop.framework.ProxyFactoryBean">

    <property?name="proxyInterfaces">

    <value>hibernatesample.service.AccountService</value>

    </property>

    <property?name="interceptorNames">

    <list>

    <value>logAspect</value>

    <value>transactionInterceptor</value>

    </list>

    </property>

    <property?name="target"><ref?bean="accountServiceTarget"/></property>

    </bean>


    ??????? 如果我再定義一個
    Service,我還是需要在使用了ProxyFactoryBeanService Bean中拷貝如下的內容而不同的是,它們之間只是更換了target屬性:

    <property?name="proxyInterfaces">

    <value>hibernatesample.service.AccountService</value>

    </property>

    <property?name="interceptorNames">

    <list>

    <value>logAspect</value>

    <value>transactionInterceptor</value>

    </list>

    </property>

    ??? ?? ???

    ??? ??? 一個好的解決配置重復的辦法是使用
    Spring配置中繼承特性,但此繼承可不是OO中的繼承,它只是將父Bean中的未聲明的屬性推到子Bean聲明(target了),而父Bean去聲明那些配置子Bean相同的內容(就是上面的內容)。簡化后的內容如下:


    <bean?id="baseServiceProxy"?class="org.springframework.aop.framework.ProxyFactoryBean"?abstract="true">

    <property?name="interceptorNames">

    <list>

    <value>logAspect</value>

    <value>transactionInterceptor</value>

    </list>

    </property>

    </bean>


    <bean?id="accountService"?parent="baseServiceProxy">

    <property?name="proxyInterfaces"><value>hibernatesample.service.AccountService</value></property>

    <property?name="target">

    <bean?class="hibernatesample.service.impl.AccountServiceImpl">

    <property?name="accountDAO"?ref="accountDAO"></property>

    </bean>

    </property>

    </bean>

    ??? ??? 對于事務聲明,除了采用通用的ProxyFactoryBean來攔截transactionInterceptor外,也可以采用TransactionProxyFactoryBean,它應該是變相的ProxyFactoryBeantransactionInterceptor。另外,可以使用TransactionProxyFactoryBeanpostInterceptors或者preInterceptors屬性來配置其他切面(通知)。


    <bean?id="baseServiceProxy"

    class
    ="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"

    abstract
    ="true">

    <property?name="transactionManager"?ref="transactionManager"?/>

    <property?name="transactionAttributes">

    <props>

    <prop?key="get*">PROPAGATION_REQUIRED,readOnly</prop>

    <prop?key="*">PROPAGATION_REQUIRED</prop>

    </props>

    </property>

    <property?name="postInterceptors">

    <ref?bean="logAspect"/>

    </property>

    </bean>


    ????在簡化Spring1.X文件配置方面,更好的選擇是使用自動代理。這里介紹一下兩個很好用的自動代理方式。

    ????第一種自動代理是使用BeanNameAutoProxyCreator,只需要指定它的beanNamesinterceptorNames,便可將interceptorNames列表中的切面(攔截器、通知)作用到匹配beanNamesBean。注意的是,beanNames可不是類名,而是配置文件中Bean名。示例如下:


    <bean?id="serviceNameAutoProxy"?class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property?name="beanNames">
    <value>*Service</value>
    </property>
    <property?name="interceptorNames">
    <list>
    <value>transactionInterceptor</value>
    <value>logAspect</value>
    </list>
    </property>
    </bean>

    ?????第二種自動代理方式是使用DefaultAdvisorAutoProxyCreator這在思想上已經是切面級的,而不是通知(攔截器)級的;也就是說,只有切面是一等公民,通知和攔截器已經不能脫離切入點而獨立工作了。還是上面的例子,使用DefaultAdvisorAutoProxyCreator的配置如下:


    <bean?id="businessServicePointcut"?class="org.springframework.aop.support.JdkRegexpMethodPointcut">

    <property?name="patterns">

    <value>hibernatesample.service.*</value>

    </property>

    </bean>

    <bean?id="logAdvice"?class="hibernatesample.service.util.LogAdvice"></bean>

    <bean?id="logAspect"?class="org.springframework.aop.support.DefaultPointcutAdvisor">

    <property?name="pointcut"?ref="businessServicePointcut"></property>

    <property?name="advice"?ref="logAdvice"></property>

    </bean>

    <bean?id="serviceClassFilter"?class="hibernatesample.service.util.ServiceClassFilter"></bean>

    <bean?id="txAdvisor"

    class
    ="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">

    <property?name="transactionInterceptor">

    <ref?bean="transactionInterceptor"/>

    </property>

    <property?name="classFilter"?ref="serviceClassFilter"></property>

    </bean>

    <bean?id="accountService"?class="hibernatesample.service.impl.AccountServiceImpl">

    <property?name="accountDAO"?ref="accountDAO"></property>

    </bean>

    <bean?id="advisorAutoProxy"?class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">

    </bean>



    ??? ??? 相比于前面的配置方式,使用DefaultAdvisorAutoProxyCreator在配置文件上有了不少變化。首先是businessServicePointcut,其patterns可是要類(或包)級別的了。變化最大的就是事務聲明了。這里引入了TransactionAttributeSourceAdvisor ,由于transactionInterceptortransactionAttributes只是方法級別的,因此需要一個classFilter來在類(包)級別上做匹配(這樣切入點就完整了),引入的 ServiceClassFilter的定義如下:


    public?class?ServiceClassFilter?implements?ClassFilter{

    public?boolean?matches(Class?c)?{

    String?name?
    =?c.getSimpleName();

    if(name.indexOf("Service")?==?-1)return?false;

    String?pg?
    =?c.getPackage().getName();

    if(!pg.startsWith("hibernatesample.service"))return?false;

    return?true;

    }

    }

    ??? ??? 好了,關于Spring1.XAOP的介紹到此結束了。在我重新整理Spring1.XAOP時,我更加覺得,Spring的配置文件太靈活了,同樣的功能會有很多種配置方式,完整的、簡潔的不一而足。對于開發者來說,需要根據自己的習慣來確定如何有效地操縱Spring1.XAOP實現。

    posted on 2007-08-30 08:38 kafka0102 閱讀(2364) 評論(1)  編輯  收藏 所屬分類: FrameworkAOP

    評論

    # re: Spring 1.x中AOP的使用 2007-08-30 12:41 JAVA面試題
    厲害學習  回復  更多評論
      

    主站蜘蛛池模板: 先锋影音资源片午夜在线观看视频免费播放 | 四虎免费影院ww4164h| 午夜不卡AV免费| 亚洲国产成人久久精品大牛影视 | 免费在线黄色电影| 特级毛片爽www免费版| 亚洲精品国产av成拍色拍| 亚洲精彩视频在线观看| 国产V亚洲V天堂无码久久久| 亚洲国产成人久久综合一区77| 成人免费看片又大又黄| 免费H网站在线观看的| 98精品全国免费观看视频| 成全视频高清免费观看电视剧 | 午夜亚洲福利在线老司机| 精品一区二区三区免费视频| 国产亚洲福利精品一区二区| 亚洲欧洲日产国码无码网站 | 看免费毛片天天看| 亚洲精品GV天堂无码男同| 国产精品亚洲自在线播放页码| 亚洲日韩中文字幕天堂不卡| 亚洲欧洲在线观看| 亚洲综合久久综合激情久久| 亚洲av最新在线网址| 久久精品国产亚洲AV麻豆~| 国产∨亚洲V天堂无码久久久| 亚洲熟妇无码另类久久久| 国产成人综合亚洲亚洲国产第一页| 亚洲国产成人爱av在线播放 | 精品无码国产污污污免费网站国产 | 十八禁视频在线观看免费无码无遮挡骂过| 国产精品永久免费视频| 亚洲视频在线免费| 少妇性饥渴无码A区免费| 全免费a级毛片免费看| 99在线观看精品免费99| 在线a免费观看最新网站| 在线视频免费观看高清| 成人免费777777| 国产成人精品男人免费|