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

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

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

    零雨其蒙's Blog

    做優(yōu)秀的程序員
    隨筆 - 59, 文章 - 13, 評(píng)論 - 58, 引用 - 0
    數(shù)據(jù)加載中……

    Spring中的AOP

    Spring 中的 AOP

    創(chuàng)建時(shí)間: 2007127 星期六

    ????????????????? ?零雨其蒙原創(chuàng),轉(zhuǎn)載請(qǐng)注明

    一、概述

    (一)基本概念

    1 、什么是AOP

    ??? 面向方面編程。所謂方面即是指日志、權(quán)限、異常處理、事務(wù)處理等。

    2 AOP3個(gè)關(guān)鍵概念

    ?? 1 )切入點(diǎn)( Pointcut ): Pointcut Join Point 的集合, Join Point 就是需要注入 Adivce 的位置,也就是需要插入日志輸出代碼、事務(wù)處理代碼等“方面”( Aspect ,也就是 AOP 中的 A )代碼的地方。

    ??? 比如我現(xiàn)在要寫一個(gè)存錢的方法: saving ()

    ??? 通常情況下我就得在這個(gè) saving ()方法前后寫些事務(wù)代碼

    ??? 如:

    ?

    ????????? logger.log(Level.INFO,”start”);

    Saving();

    ???????????????????????? logger.log(Level.INFO,”end”);

    ??????

    ???????? 對(duì)于事務(wù)代碼而言, saving ()方法的前后就都是 Join Point 了。在 Spring 中它對(duì)應(yīng) config.xml 中設(shè)定的方法,這個(gè)方法就是類( class )中需要進(jìn)行某方面處理的方法( method )。

    ?????? ? 2 )通知( Advice ): 就是指 Join Point 對(duì)應(yīng)的代碼(方法)。比如日志輸出這個(gè)方面,指的就是日志輸出的代碼或方法了。在 Spring 中,它對(duì)應(yīng)類( class )。

    ??????? 3 Advisor Poincut Advice 的配置器,它包括 Pointcut Advice ,是將 Advice 注入程序中 Pointcut 位置的代碼。在 Sping 中,它對(duì)應(yīng) config.xml 中的配置段 <bean id=logAdvisor class=”org.springframework.aop.support.RegexpMethodPointcutAdvisor”>

    ? <bean id=”logAdvisor” class=”org.springframework.aop.support.RegexpMetho

    dPointcutAdvisor”>

    ??? //advice 屬性對(duì)應(yīng)的當(dāng)然就是輸出日志的類,也就是 對(duì)應(yīng)的那個(gè)bean

    ??? <property name=”advice”>

    ???????? <ref bean=”log”/>

    ??? </property>

    ?? //patterns 屬性指出指定要代理的方法,使用的是正則表達(dá)式

    ??? <property name=”patterns”>

    ???????? <value>.*doAuditing.*</value>

    ??? </property>

    </bean>

    ?

    (二)框架圖

    ?

    創(chuàng)建代理的兩種方法

    ProxyFactoryBean

    動(dòng)態(tài)代理

    ?

    Spring4 Advice

    Interception Around

    Before

    After Returning

    Throw

    ?

    兩種代理方式

    Java 動(dòng)態(tài)代理

    CGLIB 代理

    ?

    (三)何時(shí)使用什么

    ? 1 、創(chuàng)建代理的兩種方法中首選動(dòng)態(tài)代理。

    1 種:針對(duì)某個(gè)類進(jìn)行配置。可以指定某個(gè)類中所有方法都調(diào)用方面,也可以指定某個(gè)類中的某個(gè)方法,此時(shí)由于用到正則表達(dá)式,于是需要引入 jakarta-oro-2.0.8.jar 包。

    2 種:針對(duì)某個(gè)方法進(jìn)行配置。

    ? 2 Spring4Advice

    ????? 1 種:在需要調(diào)用方面的方法前后都調(diào)用處理方面的代碼

    ????? 2 種:在需要調(diào)用方面的方法之前調(diào)用處理方面的代碼

    3 種:在需要調(diào)用方面的方法之后都調(diào)用處理方面的代碼

    4 種:在需要調(diào)用方面的方法發(fā)生異常時(shí)調(diào)用處理方面的代碼

    3 、兩種代理方式首選第1種。

    ????????? 1 種:面向接口,必須先定義接口,這是好的習(xí)慣,應(yīng)該提倡

    ????????? 2 種:當(dāng)沒有接口的時(shí)候,可以使用這種方法。需引入 cglib-nodep-2.1_3,jar 包。

    二、詳細(xì)

    (一)、創(chuàng)建AOP代理的兩種方法:

    1 、用ProxyFactoryBean創(chuàng)建AOP代理

    ?? (需要指明代理目標(biāo)類)

    1 )代理目標(biāo)類的所有方法

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

    ?"http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>

    // 下面 interceptorNames 屬性(property)中的value值就是這個(gè)beanid,其主要對(duì)應(yīng)的是寫入日志的那個(gè)類,也就是Spring AOP概念中的Advice(通知)。

    <bean id="log" class="com.gc.action.LogAround"/>

    // 要輸出日志的那個(gè)類(因?yàn)檫@種方法必須要指明代理目標(biāo)類)

    <bean id="timeBook" class="com.gc.action. timeBook "/>

    // 下面開始定義代理類,也就是ProxyFactoryBean,這是Spring自帶的類,這也是Spring AOP中的Advisor

    <bean id=”logProxy” class=”org.springframework.aop.framework.ProxyFactor

    yBean ”>

    ?// 第一個(gè)屬性,是指明要代理的類的接口,因?yàn)檫@個(gè)例子中使用的是Java動(dòng)態(tài)代理機(jī)制來實(shí)現(xiàn)AOP的,因此必須指明接口

    ??? <property name=”proxyInterfaces”>

    ??????? <value>com.gc.impl.TimeBookInterface</value>

    ??? </property>

    // 這個(gè)屬性是指明代理目標(biāo)(target)類,也就是 定義的那個(gè)類

    ?? ?<property name=”target”>

    ??????? <ref bean=”timeBook”/>

    ??? </property>

    [U1] ? // 這個(gè)屬性是用來指明插入哪個(gè)Advice,此處使用list,應(yīng)該表示這個(gè)類不只是可以調(diào)用這一個(gè)log

    ??? <property name=”interceptorNames”>

    ???????? <list>

    ???? ?????????<value>log</value> // 這個(gè)值(log)對(duì)應(yīng) 中定義的那個(gè)idlogbean

    ???????? </list>

    ??? </property>

    [U2] ? </bean>

    </beans>

    2 )代理目標(biāo)類的指定方法

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

    ?"http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>

    <bean id="log" class="com.gc.action.LogAround"/>

    <bean id="timeBook" class="com.gc.action. timeBook "/>

    // 在上一段配置文件中添加了下面這個(gè)bean,用來指明要輸出日志的指定方法(上一個(gè)例子是所有方法都輸出日志)

    <bean id=”logAdvisor” class=”org.springframework.aop.support.RegexpMetho

    dPointcutAdvisor”>

    ??? //advice 屬性對(duì)應(yīng)的當(dāng)然就是輸出日志的類,也就是 對(duì)應(yīng)的那個(gè)bean

    ??? <property name=”advice”>

    ???????? <ref bean=”log”/>

    ??? </property>

    ?? //patterns 屬性指出指定要代理的方法,使用的是正則表達(dá)式

    ??? <property name=”patterns”>

    ??? ?????<value>.*doAuditing.*</value>

    ??? </property>

    </bean>

    <bean id=”logProxy” class=”org.springframework.aop.framework.ProxyFactor

    yBean ”>

    ??? <property name=”proxyInterfaces”>

    ??????? <value>com.gc.impl.TimeBookInterface</value>

    ??? </property>

    ??? <property name=”target”>

    ??????? <ref bean=”timeBook”/>

    ??? </property>

    ??? <property name=”interceptorNames”>

    ???????? <list>

    ????????????? <value>log</value>

    ???????? </list>

    ??? </property>

    </bean>

    </beans>

    ?

    2 、用DefaultAdvisorAutoProxyCreator創(chuàng)建自動(dòng)代理

    ?? (好處:不用指明代理目標(biāo)類,如果一個(gè)大項(xiàng)目中有很多類也不必一個(gè)一個(gè)設(shè)置 AOP 代理)

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

    ?"http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>

    <bean id="log" class="com.gc.action.Log Aop "/>

    <bean id="timeBook" class="com.gc.action. timeBook "/>

    // 使用DefaultAdvisorAutoProxyCreator(紅色代碼)替代ProxyFactoryBean(綠色代碼),因?yàn)榫G色代碼的作用是為具體的類(即所謂代理目標(biāo)類)設(shè)置advice

    <bean id=”autoProxyCreator” class=”org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator”>

    <bean id=”logAdvisor [U3] ? ” class=”org.springframework.aop.support.RegexpMetho

    dPointcutAdvisor”>

    ? ?? <property name=”advice”>

    ???????? <ref bean=”log”/>

    ??? </property>

    ? ?? <property name=”patterns”>

    ?????? ??<value>.*doAuditing.*</value> [U4] ?

    ??? </property>

    </bean>

    /*<bean id=”logProxy” class=”org.springframework.aop.framework.ProxyFactor

    yBean”>

    ??? <property name=”proxyInterfaces”>

    ??????? <value>com.gc.impl.TimeBookInterface</value>

    ??? </property>

    ??? <property name=”target”>

    ??????? <ref bean=”timeBook”/>

    ??? </property>

    ??? <property name=”interceptorNames”>

    ???????? <list>

    ????????????? <value>log</value>

    ???????? </list>

    ??? </property>

    </bean>*/

    </beans>

    ?

    3 、總結(jié)

    實(shí)際上, DefaultAdvisorAutoProxyCreator ProxyFactoryBean 就是兩種代理類,前者是自動(dòng)的將 Advisor 和目標(biāo)類聯(lián)系起來,后者是通過指定的方式,將目標(biāo)類和 Advisor 組合起來。

    advisor ,對(duì)應(yīng)的就是 org.springframework.aop.support.RegexpMethodPointcutAdvisor ,通過正則表達(dá)式來匹配類中的方法(設(shè)定 Pointcut )。

    (二)Spring四種通知(Advice)形式

    1 Interception Around通知

    ?????? 1 )負(fù)責(zé)輸出日志的類

    import org.aopalliance.intercept.MethodInterceptor;

    import org.aopalliance.intercept.MethodInvocation;

    import org.apache.log4j.Level;

    import org.apache.log4j.Logger;

    ?

    public class LogAround implements MethodInterceptor{

    ????? private Logger logger = Logger.getLogger(this.getClass().getName());

    ???

    ??? public Objectinvoke(MethodInvocation methodInvocation) throws Throwable {

    ?????????? logger.log(Level.INFO, methodInvocation.getArguments()[0] + " 開始審核數(shù)據(jù)....");?

    ??????? try {

    ????????? Object result = methodInvocation.proceed();

    ????????? return result;

    ??????? }

    ??????? finally {

    ???????????????? logger.log(Level.INFO, methodInvocation.getArguments()[0] + " 審核數(shù)據(jù)結(jié)束....");

    ??????? }???????

    ?? }

    }?????

    ? 2 )配置文件

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

    ?"http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>

    <bean id="log" class="com.gc.action.Log Aop "/>

    <bean id="timeBook" class="com.gc.action. timeBook "/>

    <bean id=”logProxy” class=”org.springframework.aop.framework.ProxyFactor

    yBean”>

    ??? <property name=”proxyInterfaces”>

    ??????? <value>com.gc.impl.TimeBookInterface</value>

    ??? </property>

    ??? <property name=”target”>

    ??????? <ref bean=”timeBook”/>

    ??? </property>

    ??? <property name=”interceptorNames”>

    ???????? <list>

    ????????????? <value>log</value>

    ???????? </list>

    ??? </property>

    </bean>

    </beans>

    ?

    ?

    2 Before通知

    1 )負(fù)責(zé)輸出日志的類

    import java.lang.reflect.Method;

    ?

    import org.apache.log4j.Level;

    import org.apache.log4j.Logger;

    import org.springframework.aop.MethodBeforeAdvice;

    ?

    public class LogBefore implements MethodBeforeAdvice {

    ?????? private Logger logger = Logger.getLogger(this.getClass().getName());

    ???

    ??? public void before(Method method, Object[] args, Object target) throws Throwable {

    ????????????? logger.log(Level.INFO, args[0] + " 開始審核數(shù)據(jù) ....");

    ?? }

    }

    2 )配置文件

    ???? 與第 1 種方法相同。

    3 After Returning通知

    1 )負(fù)責(zé)輸出日志的類

    import java.lang.reflect.Method;

    ?

    import org.apache.log4j.Level;

    import org.apache.log4j.Logger;

    import org.springframework.aop.AfterReturningAdvice;

    ?

    public class LogAfterReturning implements AfterReturningAdvice {

    ?????? private Logger logger = Logger.getLogger(this.getClass().getName());

    ???

    ??? public void afterReturning(Method method, Object[] args, Object target) throws Throwable {

    ????????????? logger.log(Level.INFO, args[0] + " 開始審核數(shù)據(jù) ....");

    ?? }

    }

    2 )配置文件

    ???? 與第 1 種方法相同。

    4 Throw通知

    1 )負(fù)責(zé)輸出日志的類

    import java.lang.reflect.Method;

    ?

    import org.apache.log4j.Level;

    import org.apache.log4j.Logger;

    import org.springframework.aop.ThrowsAdvice;

    ?

    public class LogThrow implements ThrowsAdvice {

    ?????? private Logger logger = Logger.getLogger(this.getClass().getName());

    ???

    ??? public void afterThrowing(Method method, Object[] args, Object target,Throwable subclass) throws Throwable {

    ????????????? logger.log(Level.INFO, args[0] + " 開始審核數(shù)據(jù) ....");

    ?? }

    }

    2 )配置文件

    ???? 與第 1 種方法相同。

    5 、測(cè)試程序

    ?? 1 )使用自動(dòng)代理

    public class TestHelloWorld {

    ?????? public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

    ????????????? ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");

    ????????????? TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("timeBook");

    ????????????? timeBookProxy.doAuditing(" 張三 ");

    ?? 2 )不使用自動(dòng)代理

    public class TestHelloWorld {

    ?????? public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

    ????????????? ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");

    ????????????? TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("logProxy");

    ????????????? timeBookProxy.doAuditing(" 張三 ");

    使用自動(dòng)代理,則直接調(diào)用該類的名字( timeBook ),否則調(diào)用相應(yīng)的代理 bean logProxy )。因?yàn)榈?/span> 1 種方法中根本就沒有對(duì)應(yīng)的代理 bean ,只有一個(gè) Spring 的自動(dòng)代理類

    ?

    (三)Spring兩種代理方式

    1 Java動(dòng)態(tài)代理

    1 )配制文件(不使用自動(dòng)代理)

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

    ?"http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>

    <bean id="log" class="com.gc.action.Log Aop "/>

    <bean id="timeBook" class="com.gc.action. timeBook "/>

    <bean id=”logProxy” class=”org.springframework.aop.framework.ProxyFactor

    yBean”>

    ??? <property name=”proxyInterfaces”>

    ??????? <value>com.gc.impl.TimeBookInterface</value>

    ??? </property>

    ??? <property name=”target”>

    ??????? <ref bean=”timeBook”/>

    ??? </property>

    ??? <property name=”interceptorNames”>

    ???????? <list>

    ????????????? <value>log</value>

    ???????? </list>

    ??? </property>

    </bean>

    </beans>

    ?

    2 )測(cè)試程序

    public class TestHelloWorld {

    ?????? public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

    ????????????? ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");

    ????????????? TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("logProxy");

    ????????????? timeBookProxy.doAuditing(" 張三 ");

    ?

    2 CGLIB代理

    1 )配制文件(不使用自動(dòng)代理)

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

    ?"http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>

    <bean id="log" class="com.gc.action.Log Aop "/>

    <bean id="timeBook" class="com.gc.action. timeBook "/>

    <bean id=”logProxy” class=”org.springframework.aop.framework.ProxyFactor

    yBean”>

    // 增加如下屬性,就表示使用的是CGLIB代理(對(duì)目標(biāo)類直接代理)

    ??? <property name=”proxyTargetClass”>

    ??????? <value>true</value>

    ??? </property>

    ?? /* 然后去掉下面的屬性,也就是說此種方法不需要面向接口,或不需要指出接口

    <property name=”proxyInterfaces”>

    ??????? <value>com.gc.impl.TimeBookInterface</value>

    ??? </property>*/

    ??? <property name=”target”>

    ??????? <ref bean=”timeBook”/>

    ??? </property>

    ??? <property name=”interceptorNames”>

    ???????? <list>

    ??????????? ??<value>log</value>

    ???????? </list>

    ??? </property>

    </bean>

    </beans>

    ?

    2 )測(cè)試程序

    public class TestHelloWorld {

    ?????? public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {

    ????????????? ApplicationContext actx=new FileSystemXmlApplicationContext("config.xml");

    ????????????? TimeBookInterface timeBookProxy = (TimeBookInterface)actx.getBean("logProxy");

    ????????????? timeBookProxy.doAuditing(" 張三 ");

    ?

    ?


    ?[U1] Join Point

    ?[U2] Advice

    ?[U3] 這個(gè)名字自己可以隨便起

    ?[U4] 如果想對(duì)類的所有方法都有效,就要寫成 .*.*

    posted on 2007-01-31 17:10 零雨其蒙 閱讀(1807) 評(píng)論(1)  編輯  收藏 所屬分類: 學(xué)習(xí)筆記

    評(píng)論

    # re: Spring中的AOP  回復(fù)  更多評(píng)論   

    最近也在學(xué)習(xí)Spring,強(qiáng)烈支持,多多交流哦!
    2007-02-01 00:33 | 施偉
    主站蜘蛛池模板: 日韩av无码免费播放| 亚洲爆乳无码一区二区三区| 久久久久久亚洲av无码蜜芽 | 午夜精品在线免费观看| 亚洲mv国产精品mv日本mv| 国产妇乱子伦视频免费| 亚洲成av人片在线看片| 一级毛片免费播放| 久久精品国产亚洲av麻豆小说 | 国产精品久久香蕉免费播放| 亚洲爆乳无码专区www| 在线免费观看韩国a视频| 久久亚洲精品无码gv| 亚洲AⅤ永久无码精品AA| 九九九精品视频免费| 久久国产成人亚洲精品影院| 中文永久免费观看网站| 亚洲国产精品无码久久久秋霞2| 国产无遮挡裸体免费视频在线观看| 久久精品国产精品亚洲艾 | 婷婷综合缴情亚洲狠狠尤物| 一级做a爰片久久毛片免费陪 | 99久久免费中文字幕精品| 亚洲精品网站在线观看你懂的| 欧洲一级毛片免费| 成人亚洲国产va天堂| 国产精品嫩草影院免费| 看免费毛片天天看| 国产亚洲日韩一区二区三区| 野花香高清视频在线观看免费 | 亚洲日本韩国在线| 日本道免费精品一区二区| 亚洲视频免费在线看| 国内免费高清在线观看| 国产青草亚洲香蕉精品久久| 久久久久久A亚洲欧洲AV冫| 日本高清免费观看| 亚洲91精品麻豆国产系列在线| 暖暖免费高清日本一区二区三区| 羞羞视频在线免费观看| 亚洲成色www久久网站夜月|