8 -- 深入使用Spring -- 4...6 AOP代理:基於注解的XML配置文件的管理方式


      8.4.6 基於XML配置文件的管理方式

        Spring 2.x 提供一個新的aop:命名空間來定義切面、切入點和增強處理。

        XML配置方式優點:

          ⊙ 如果應用沒有使用JDK 1.5 以上版本,那么應用只能使用XML配置方式來管理切面、切入點和增強處理等。

          ⊙ 采用XML配置方式時對早期的Spring用戶來說更加習慣,而且這種方式允許使用純粹的POJO來支持AOP。當使用AOP作為工具來配置企業服務時,XML會是一個很好的選擇。

        當使用XML風格時,可以在配置文件中清晰地看出系統中存在那些切面。

        XML配置費方式缺點:

          ⊙ 使用XML配置方式不能將切面、切入點、增強處理等封裝到一個地方。如果需要查看切面、切入點、增強處理,必須同時結合Java文件和XML配置文件來查看;但使用@AspectJ時,則只需要一個單獨的類文件即可看到切面、切入點和增強處理的全部信息。

          ⊙ XML配置方式比@AspectJ方式有更多的限制:僅支持“singleton”切面Bean,不能在XML中組合多個命名連接點的聲明。

        @AspectJ切面還有一個優點,就是能被Spring AOP和AspectJ同時支持,如果有一天需要將應用改為使用AspectJ來實現AOP,使用@AspectJ將非常容易遷移到基於AspectJ的AOP實現中。

        在Spring 配置文件中,所有的切面、切入點和增強處理都必須定義在<aop:config.../>元素內部。

        <beans.../>元素下可以包含多個<aop:config.../>元素,一個<aop:config>可以包含pointcut、advisor和aspect元素,且這三個元素必須按照此順序來定義。

        <aop:config.../>元素所包含的子元素如圖:

          圖圖圖圖圖圖圖圖圖圖圖圖圖圖圖圖圖圖

          圖                圖

          圖                圖

          圖                圖

          圖                圖

          圖                圖

          圖                圖

          圖圖圖圖圖圖圖圖圖圖圖圖圖圖圖圖圖圖

        注意:

          使用<aop:config.../>方式進行配置時,可能與Spring的自動代理方式相沖突,例如使用<aop:aspectj-autoproxy/>或類似方式顯式啟用了自動代理,則可能會導致出現問題(比如有些增強處理沒有被織入)。因此建議:要么全部使用<aop:config.../>配置方式,要么全部使用自動代理方式,不要兩者混合使用。

        1.配置切面

          定義切面使用<aop:aspect.../>元素,使用該元素來定義切面時,其實質是將一個已有的Spring Bean轉換成切面Bean,所以需要先定義個一個普通的Spring Bean。

          因為切面Bean可以當成一個普通的Spring Bean來配置,所以完全可以為該切面Bean 配置依賴注入。當切面Bean定義完成后,通過在<aop:aspect.../>元素中使用ref屬性來引用該Bean,就可以該Bean轉換成一個切面Bean了。

          配置<aop:aspect.../>元素時可以指定如下三個屬性:

            ⊙ id : 定義該切面的標識名。

            ⊙ ref : 用於該ref屬性所引用的普通Bean轉換為切面Bean。

            ⊙ order : 指定該切面Bean的優先級,該屬性的作用與前面@AspectJ中的@Order注解、Ordered接口的作用完全一樣,order屬性值越小,該切面對應的優先級越高。

          擴展:關於Order接口點這里,暫時懶得看。留在明天的明天的明天的明天的明天有空再看吧。

          配置定義一個切面:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd語義約束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:P="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 定義一個普通Bean實例,該Bean實例將作為Aspect Bean -->
    <bean id="afterAdviceBean" class="edu.pri.lime._8_4_6.xmlaspect.AfterAdviceTest" />

    <aop:config>
        <!-- 將容器中AfterAdviceBean轉換成切面Bean 切面Bean的新名稱為:afterAdviceAspect -->
        <aop:aspect id="afterAdviceAspect" ref="afterAdviceBean"
            order="100"/>
    </aop:config>


</beans>

          由於Spring支持將切面Bean當成普通Bean來管理,所以完全可以利用依賴注入來管理切面Bean,管理切面Bean的屬性值、依賴管理等。

        2.配置增強處理

          使用XML一樣可以配置Before、After、AfterReturning、AfterThrowing、Around五種增強處理,而且完全支持和@AspectJ完全一樣的語義。

          使用XML配置增強處理分別依賴於如下幾個元素:

            ⊙ <aop:before.../> : 配置Before增強處理。

            ⊙ <aop:after.../> : 配置After增強處理。

            ⊙ <aop:after-returning.../>:配置AfterReturning增強處理。

            ⊙ <aop:after-throwing.../>:配置AfterThrowing增強處理。

            ⊙ <aop:around.../> : 配置AfterThrowing增強處理。

          這些元素都不支持使用子元素,但通常可指定如下屬性:

            ⊙ pointcut : 該屬性指定一個切入表達式,Spring將在匹配該表達式的連接點時織入該增強處理。

            ⊙ pointcut-ref : 該屬性指定一個已經存在的切入點名稱,通常pointcut和pointcut-ref兩個屬性只需要使用其中之一。

            ⊙ method : 該屬性指定一個方法名,指定該切面Bean的該方法轉換為增強處理。

            ⊙ throwing : 該屬性只對<after-throwing.../>元素有效,用於指定一個形參名,AfterThrowing增強處理方法可通過該形參訪問目標方法所拋出的異常。

            ⊙ returning : 該屬性只對<after-returning.../>元素有效,用於指定一個形參名,AfterReturning增強處理方法可通過該形參訪問目標方法的返回值。

          當定義切入點表達式時,XML配置方式和@AspectJ注解方式支持完全相同的切入點指示符,一樣可以支持execution、within、args、this、target和bean等切入點指示符。

          XML配置方式和@AspectJ注解方式一樣支持組合切入點表達式,但XML配置方式不再使用簡單的&&、|| 和 ! 作為組合運算符(因為直接在XML文件中需要使用實體引用來表示它們),而是使用如下三個組合運算符:and、or和not。

          Class : 刪除Annotation注釋--FourAdviceTest

package edu.pri.lime._8_4_6.xmlaspect;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class FourAdviceTest {

    public Object processTx(ProceedingJoinPoint jp) throws Throwable{
        System.out.println("Around 增強 : 執行目標方法之前,模擬開始事務...");
        Object[] args = jp.getArgs();
        if(null != args && args.length > 0 && args[0].getClass() == String.class){
            args[0] = "【增加的前綴】" + args[0];
        }
        Object rvt = jp.proceed(args);
        System.out.println("Around 增強 : 執行目標方法后,模擬結束事務...");
        if(null != rvt && rvt instanceof Integer){
            rvt = (Integer)rvt * (Integer)rvt;
        }
        return rvt;
    }
    
    public void authorith(JoinPoint jp){
        System.out.println("Before 增強 : 模擬執行權限檢查");
        System.out.println("Before 增強 : 被織入增強處理的目標方法為 : " + jp.getSignature().getName());
        System.out.println("Before 增強 : 目標方法的參數為 : " + Arrays.toString(jp.getArgs()));
        System.out.println("Before 增強 : 被織入增強處理的目標對象為 : " + jp.getTarget());
        System.out.println("Before 增強 : AOP框架為目標對象生成的代理對象為 : " + jp.getThis());
    }
    
    public void log(JoinPoint jp,Object rvt){
        System.out.println("AfterReturning 增強 : 獲取目標方法返回值 : " + rvt);
        System.out.println("AfterReturning 增強 : 模擬記錄日志功能...");
        System.out.println("AfterReturning 增強 : 被織入增強處理的目標方法為 : " + jp.getSignature().getName());
        System.out.println("AfterReturning 增強 : 目標方法的參數為 : " + Arrays.toString(jp.getArgs()));
        System.out.println("AfterReturning 增強 : 被織入增強處理的目標對象為 : " + jp.getTarget());
        System.out.println("AfterReturning 增強 : AOP框架為目標對象生成的代理對象為  : " + jp.getThis());
    }
    
    public void release(JoinPoint jp){
        System.out.println("After 增強 : 模擬方法結束后的釋放資源...");
        System.out.println("After 增強 : 被織入增強處理的目標方法為 : " + jp.getSignature().getName());
        System.out.println("After 增強 : 目標方法的參數為 : " + Arrays.toString(jp.getArgs()));
        System.out.println("After 增強 : 被織入增強處理的目標對象為 : " + jp.getTarget());
        System.out.println("After 增強 : AOP框架為目標對象生成的代理對象為  : " + jp.getThis());
    }
}

          Class : SecondAdviceTest

package edu.pri.lime._8_4_6.xmlaspect;

public class SecondAdviceTest {

//    視圖通過該arg形參來訪問目標方法的參數值,這需要在配置該切面Bena時使用args切入點指示符
    public void authorith(String arg){
        System.out.println("目標方法的參數為 : " + arg);
        System.out.println("①號Before增強 : 模擬執行權限檢查");
    }
}

          XML : 

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd語義約束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:P="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <aop:config>
        <aop:aspect id="fourAdviceAspect" ref="fourAdviceBean"
            order="2">
            <!-- 定義一個Around增強處理 直接指定切入點表達式 以切面Bean中的processTx()方法作為增強處理方法 -->
            <aop:around method="processTx"
                pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..))" />
            <!-- 定義一個Before增強處理 直接指定切入點表達式 以切面Bean中的authority()方法作為增強處理方法 -->
            <aop:before method="authority"
                pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..))" />
            <!-- 定義一個AfterReturning增強處理 直接指定切入點表達式 以切面Bean中的log()方法作為增強處理方法 -->
            <aop:after-returning method="log"
                pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..))"
                returning="rvt" />
            <!-- 定義一個After增強 直接指定切入點表達式 以切面Bean中的release()方法作為增強處理方法 -->
            <aop:after method="release"
                pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..))" />
        </aop:aspect>
        <!-- 將secondAdviceBean轉換成切面Bean 切面Bean的新名稱為:secondAdviceAspect 指定該切面的優先級為1,該切面里的增強處理將被有限織入 -->
        <aop:aspect id="secondAdviceAspect" ref="secondAdviceBean"
            order="1">
            <aop:before method="authority"
                pointcut="execution(* edu.pri.lime._8_4_6.xmladvice.bean.impl.*.*(..)) and args(arg)" />
        </aop:aspect>
    </aop:config>

    <bean id="hello" class="edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl" />

    <bean id="fourAdviceBean" class="edu.pri.lime._8_4_6.xmladvice.FourAdviceTest" />

    <bean id="secondAdviceBean" class="edu.pri.lime._8_4_6.xmladvice.SecondAdviceTest" />
</beans>

          Class : AspectTest

package edu.pri.lime._8_4_6.xmladvice.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import edu.pri.lime._8_4_6.xmladvice.bean.Hello;

public class AspectTest {

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("app_8_4_6_advice.xml");
        Hello hello = (Hello) ctx.getBean("hello");
        hello.foo();
        System.out.println("--------------Bang bang, he shot me down----------------");
        hello.addUser("lime", "1234");
        System.out.println("--------------C'est la vie----------------");
        hello.deleteUser("lime");
    }
}

          Console : 

Around 增強 : 執行目標方法之前,模擬開始事務...
22:03:38.837 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'Before 增強 : 模擬執行權限檢查
② Before 增強 : 被織入增強處理的目標方法為 : foo
② Before 增強 : 目標方法的參數為 : []
② Before 增強 : 被織入增強處理的目標對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
② Before 增強 : AOP框架為目標對象生成的代理對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
調用HelloImpl組件的foo()方法...
Around 增強 : 執行目標方法后,模擬結束事務...
22:03:38.840 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean' AfterReturning 增強 : 獲取目標方法返回值 : null
AfterReturning 增強 : 模擬記錄日志功能...
AfterReturning 增強 : 被織入增強處理的目標方法為 : foo
AfterReturning 增強 : 目標方法的參數為 : []
AfterReturning 增強 : 被織入增強處理的目標對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
AfterReturning 增強 : AOP框架為目標對象生成的代理對象為  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
22:03:38.840 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean' After 增強 : 模擬方法結束后的釋放資源...
After 增強 : 被織入增強處理的目標方法為 : foo
After 增強 : 目標方法的參數為 : []
After 增強 : 被織入增強處理的目標對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
After 增強 : AOP框架為目標對象生成的代理對象為  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
--------------Bang bang, he shot me down----------------
22:03:38.841 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
Around 增強 : 執行目標方法之前,模擬開始事務...
22:03:38.841 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
② Before 增強 : 模擬執行權限檢查
② Before 增強 : 被織入增強處理的目標方法為 : addUser
② Before 增強 : 目標方法的參數為 : [【增加的前綴】lime, 1234]
② Before 增強 : 被織入增強處理的目標對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
② Before 增強 : AOP框架為目標對象生成的代理對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
調用HelloImpl組件的addUser()方法添加用戶 : 【增加的前綴】lime
Around 增強 : 執行目標方法后,模擬結束事務...
22:03:38.841 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
AfterReturning 增強 : 獲取目標方法返回值 : 484
AfterReturning 增強 : 模擬記錄日志功能...
AfterReturning 增強 : 被織入增強處理的目標方法為 : addUser
AfterReturning 增強 : 目標方法的參數為 : [【增加的前綴】lime, 1234]
AfterReturning 增強 : 被織入增強處理的目標對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
AfterReturning 增強 : AOP框架為目標對象生成的代理對象為  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
22:03:38.841 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
After 增強 : 模擬方法結束后的釋放資源...
After 增強 : 被織入增強處理的目標方法為 : addUser
After 增強 : 目標方法的參數為 : [【增加的前綴】lime, 1234]
After 增強 : 被織入增強處理的目標對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
After 增強 : AOP框架為目標對象生成的代理對象為  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
--------------C'est la vie----------------
22:03:38.849 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'secondAdviceBean'
目標方法的參數為 : lime
① Before增強 : 模擬執行權限檢查 22:03:38.850 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
Around 增強 : 執行目標方法之前,模擬開始事務...
22:03:38.850 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean' ② Before 增強 : 模擬執行權限檢查 ② Before 增強 : 被織入增強處理的目標方法為 : deleteUser ② Before 增強 : 目標方法的參數為 : [【增加的前綴】lime] ② Before 增強 : 被織入增強處理的目標對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0 ② Before 增強 : AOP框架為目標對象生成的代理對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
調用HelloImpl組件的deleteUser()方法刪除用戶 : 【增加的前綴】lime
Around 增強 : 執行目標方法后,模擬結束事務...
22:03:38.850 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
AfterReturning 增強 : 獲取目標方法返回值 : 54756
AfterReturning 增強 : 模擬記錄日志功能...
AfterReturning 增強 : 被織入增強處理的目標方法為 : deleteUser
AfterReturning 增強 : 目標方法的參數為 : [【增加的前綴】lime]
AfterReturning 增強 : 被織入增強處理的目標對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
AfterReturning 增強 : AOP框架為目標對象生成的代理對象為  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
22:03:38.850 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'fourAdviceBean'
After 增強 : 模擬方法結束后的釋放資源...
After 增強 : 被織入增強處理的目標方法為 : deleteUser
After 增強 : 目標方法的參數為 : [【增加的前綴】lime]
After 增強 : 被織入增強處理的目標對象為 : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0
After 增強 : AOP框架為目標對象生成的代理對象為  : edu.pri.lime._8_4_6.xmladvice.bean.impl.HelloImpl@40238dd0

        3.配置切入點

          XML配置方式也可以通過定義切入點來重用切入點表達式,Spring提供了<aop:pointcut.../>元素來定義切入點。

          當把<aop:pointcut.../>元素作為<aop:config.../>的子元素定義時,表明該切入點可別多個切面共享;

          當把<aop:pointcut.../>元素作為<aop:aspect.../>的子元素定義時,表明該切入點只能在切面中有效;

          配置<aop:pointcut.../>元素時通常需要指定如下兩個屬性:

            ⊙ id : 指定該切入點的標識名;

            ⊙ expression : 指定該切入點關聯的切入點表達式;

          配置切入點表達式Demo : 

    <aop:config>
        <aop:pointcut expression="execution(* edu.pri.lime._8_4_6.pointcut.demo.bean.impl.*.*(..))" id="myPointcut"/>
    </aop:config>

          配置已有的切入點Demo :

    <aop:config>
        <aop:pointcut expression="edu.pri.lime._8_4_6.pointcut.demo.SystemArchitecture.myPointcut()" id="myPointcut"/>
    </aop:config>

          Class : RepairAspect

package edu.pri.lime._8_4_6.pointcut;

public class RepairAspect {

    public void doRecoveryActions(Throwable ex){
        System.out.println("目標方法中拋出的異常 : " + ex);
        System.out.println("模擬Advice對異常的修復...");
    }
}

          XML : 

<?xml version="1.0" encoding="UTF-8"?>
<!-- Spring 配置文件的根元素,使用Spring-beans-4.0.xsd語義約束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:P="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <bean id="hello" class="edu.pri.lime._8_4_6.pointcut.bean.impl.HelloImpl"/>
    <bean id="repairAspect" class="edu.pri.lime._8_4_6.pointcut.RepairAspect"/>

    <aop:config>
        <aop:pointcut expression="execution(* edu.pri.lime._8_4_6.pointcut.bean.impl.*.*(..))" id="myPointcut"/>
        <aop:aspect id="afterThrowingAdviceBean" ref="repairAspect">
            <aop:after-throwing method="doRecoveryActions" pointcut-ref="myPointcut" throwing="ex"/>
        </aop:aspect>
    </aop:config>
</beans>

          Class : PointcutTest

package edu.pri.lime._8_4_6.pointcut.main;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import edu.pri.lime._8_4_6.pointcut.bean.Hello;

public class PointcutTest {

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("app_8_4_6_pointcut.xml");
        Hello hello = (Hello) ctx.getBean("hello");
        hello.addUser("li", "2345");
    }
}

          Console : 

調用組件的addUser方法添加用戶 : li 22:44:03.511 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'repairAspect' 目標方法中拋出的異常 : java.lang.IllegalArgumentException: name 長度小於3 或 大於10 模擬Advice對異常的修復...
Exception in thread "main" java.lang.IllegalArgumentException: name 長度小於3 或 大於10 
    at edu.pri.lime._8_4_6.pointcut.bean.impl.HelloImpl.addUser(HelloImpl.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:58)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy2.addUser(Unknown Source)
    at edu.pri.lime._8_4_6.pointcut.main.PointcutTest.main(PointcutTest.java:13)

 

啦啦啦

啦啦啦

啦啦啦

啦啦啦


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM