<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面試題
    厲害學習  回復  更多評論
      

    主站蜘蛛池模板: 亚洲国产精品白丝在线观看| 亚洲精品熟女国产| 久久这里只精品热免费99| 亚洲精品在线播放视频| 国产老女人精品免费视频| 日韩在线一区二区三区免费视频| 亚洲综合无码精品一区二区三区| 日韩插啊免费视频在线观看| 亚洲日本在线电影| 亚洲成色WWW久久网站| 一个人免费高清在线观看| eeuss免费天堂影院| 亚洲视频在线免费播放| 亚洲成a人片在线观看日本麻豆| xxxxwww免费| 国产日韩AV免费无码一区二区| 亚洲欧洲日产国码在线观看| 国产乱子伦精品免费女| 午夜免费福利小电影| 黄网站色视频免费看无下截| 4444亚洲国产成人精品| 国产福利电影一区二区三区,亚洲国模精品一区 | 99视频在线精品免费观看6| 亚洲欧美自偷自拍另类视| 亚洲男人都懂得羞羞网站| 亚洲国产成人精品女人久久久 | 美女视频黄的免费视频网页| 亚洲美女视频一区二区三区| 免费看h片的网站| 亚洲已满18点击进入在线观看| 日日操夜夜操免费视频| 最近中文字幕大全免费版在线| 亚洲第一二三四区| 亚洲精品无码你懂的网站| 鲁丝片一区二区三区免费| 特级毛片aaaa级毛片免费| 亚洲熟女乱色一区二区三区 | 国产亚洲免费的视频看| 一本到卡二卡三卡免费高| 男人的天堂av亚洲一区2区| 亚洲 欧洲 自拍 另类 校园|