十一 Spring-AOP切面編程(3)

目錄

1. Web MVC發(fā)展史歷程
2.Spring概要
3.Spring-依賴注入概要(IOC)
4.屬性注入的三種實現(xiàn)方式
5.Spring-IoC XML裝配
6.Spring-XML設置Bean的值
7.Spring-IoC 注解(1)
8.Spring-IoC 注解(2)
9.Spring-AOP切面編程(1)
10.Spring-AOP切面編程(2)
11.Spring-AOP切面編程(3)

六淹父、基于@Aspect注解編程(重點)

1柜与、說明

Spring 使用了和AspectJ 一樣的注解并使用AspectJ來做切入點解析和匹配。但是,AOP在運行時仍舊是純的Spring AOP,并不依賴于AspectJ的編譯器或者織入器(weaver)(編譯器與織入器暫時不要管)

2、啟用@AspectJ支持

  1. 說明
    為了在Spring中使用@AspectJ切面羊初,你首先必須啟用Spring對@AspectJ切面配置的支持,并確保開啟自動代理什湘。自動代理是指Spring會判斷一個bean是否使用了一個或多個切面通知长赞,并據(jù)此自動生成相應的代理以攔截其方法調(diào)用,并且確保通知在需要時執(zhí)行
  2. 新建spring-aspect.xml配置文件
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
        <context:component-scan base-package="com.wener.example.aop.aspect"/>
     <!-- 有了這個Spring就能夠自動掃描被@Aspect標注的切面了 -->
        <!-- 開啟自動代理 -->    
        <aop:aspectj-autoproxy/>
    </beans>
    

2闽撤、聲明一個切面

  1. 說明
    在代碼中定義一個類任意在類上使用@Aspect注解
  2. 示例代碼
    import org.aspectj.lang.annotation.Aspect;
    @Aspect
    public class LogAspect {
    }
    

3得哆、聲明一個切入點

  1. 說明
    切入點決定了連接點關注的內(nèi)容,使得我們可以控制通知什么時候執(zhí)行腹尖。Spring AOP只支持Spring bean的方法執(zhí)行連接點柳恐。所以你可以把切入點看做是Spring bean上方法執(zhí)行的匹配。一個切入點聲明有兩個部分:
    • 包含名字和任意參數(shù)的簽名:一個切入點簽名通過一個普通的方法定義來提供热幔,并且切入點表達式使用@Pointcut注解來表示(作為切入點簽名的方法必須返回void 類型)
    • 切入點表達式:切入點表達式?jīng)Q定了我們關注哪些方法的執(zhí)行,詳細表達式語法后面在說乐设。
  2. 語法格式
    @Pointcut(value="", argNames = "")
    
  3. 參數(shù)說明
    • value
      指定切入點表達式
    • argNames
      指定命名切入點方法參數(shù)列表參數(shù)名字,可以有多個用“绎巨,”分隔近尚,這些參數(shù)將傳遞給通知方法同名的參數(shù)
  4. 示例代碼
    @Aspect
    public class LogAspect {
        // 也可以在通知上定義,當需要復用切入點的時候
        @Pointcut("execution(* com.wener.example.aop.aspect.*.*(..))")  
        // 返回值 必須是void類型
        public void log() {
        }
    }
    
  5. 備注
    切入點的定義是非必要的,也可以直接在通知上使用切入點表達式

4、聲明通知

4.1场勤、說明

通知是跟一個切入點表達式關聯(lián)起來的戈锻,并且在切入點匹配的方法執(zhí)行之前或者之后或者前后運行。 切入點表達式可能是指向已命名的切入點的簡單引用或者是一個已經(jīng)聲明過的切入點表達式和媳,通知的類型就是我們前面提到過的類型

4.2格遭、前置通知

  1. 說明
    在關注點執(zhí)行前運行的方法,切面里使用 @Before 注解聲明前置通知
  2. 語法格式
    @Before(value = "", argNames = "")
    
  3. 參數(shù)說明
    • value :指定切入點表達式或切入點名字留瞳;
    • argNames: 用來接收AspectJ表達式中的參數(shù),并指定通知方法中的參數(shù)
  4. 示例代碼
    import org.springframework.stereotype.Component;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.annotation.Before;
    @Aspect
    @Component
    public class LogAspect {
        /**
         * @Pointcut() 切入點表達式
         */
        @Pointcut("execution(* com.wener.example.aop.aspect.*.*(..))")
        public void logPointcut() {
        }
        /**
         * @Before 前置通知
         * value:指定切入點表達式或命名切入點拒迅;
         * argNames:與Schema方式配置中的同義;
         */
        @Before("logPointcut()")
        public void before() {
            System.out.println("前置通知");
        }
    }
    

4.3她倘、后置通知(最終通知)

  1. 說明
    不論一個方法是如何結束的璧微,最終通知都會運行。使用@After 注解來聲明硬梁。最終通知必須準備處理正常返回和異常返回兩種情況前硫。通常用它來釋放資源。相當于異常處理里finally的代碼
  2. 語法格式
    @After(value = "", argNames = "")
    
  3. 參數(shù)
    • value :指定切入點表達式或切入點名字荧止;
    • **argNames: **用來接收AspectJ表達式中的參數(shù),并指定通知方法中的參數(shù)
  4. 示例代碼
    import org.springframework.stereotype.Component;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Before;
    @Aspect
    @Component
    public class LogAspect {
        /**
         * @Pointcut() 切入點表達式
         */
        @Pointcut("execution(* com.wener.example.aop.aspect.*.*(..))")
        public void logPointcut() {
        }
        /**
         * @After 后置通知 
         */
        @After(value = "logPointcut()")
        public void after() {
            System.out.println("后置通知");
        }
    }
    

4.4屹电、返回通知

  1. 說明
    返回后通知通常在一個匹配的方法返回的時候執(zhí)行阶剑。使用 @AfterReturning 注解來聲明
  2. 語法格式
    @AfterReturning(value="",pointcut="",returning="",argNames="")
    
  3. 參數(shù)說明
    • value:指定切入點表達式或切入點名字;
    • pointcut:指定切入點表達式或命名切入點嗤详,如果指定了將覆蓋value屬性的个扰,pointcut具有高優(yōu)先級瓷炮;
    • returning:如果你想獲取方法的返回值可以使用該參數(shù),在通知方法中定義參數(shù)就可以了
    • argNames:用來接收AspectJ表達式中的參數(shù),并指定通知方法中的參數(shù)
  4. 示例代碼
    import org.springframework.stereotype.Component;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.ProceedingJoinPoint;
    @Aspect
    @Component
    public class LogAspect {
        /**
         * @Pointcut() 切入點表達式
         */
        @Pointcut("execution(* com.wener.example.aop.aspect.*.*(..))")
        public void logPointcut() {
        }
     /**
      * 不獲取方法的返回值
         */
        @AfterReturning(value = "logPointcut()")
        public void AfterReturning1() {
            System.out.println("異常通知");
        }
        /**
         * 獲取方法的返回值
         * returning的賦值的名字,必須跟通知方法中參數(shù)的名字保持一致
         */
        @AfterReturning(value = "logPointcut()", returning = "val")
        public Object afterReturning(Object val) {
            System.out.println("返回后通知");
            return val;
        }
    }
    

4.5葱色、異常通知

  1. 說明
    拋出異常通知在一個方法拋出異常后執(zhí)行。使用@AfterThrowing注解來聲明
  2. 語法格式
    @AfterThrowing(value="",pointcut="",throwing="",argNames="")
    
  3. 參數(shù)說明
    • value:指定切入點表達式或命名切入點娘香;
    • pointcut:指定切入點表達式或命名切入點苍狰,如果指定了將覆蓋value屬性的,pointcut具有高優(yōu)先級烘绽;
    • throwing:異常類型淋昭;并且在通知方法中定義異常參數(shù);
    • argNames:用來接收AspectJ表達式中的參數(shù),并指定通知方法中的參數(shù)安接;
  4. 示例代碼
    import org.springframework.stereotype.Component;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.ProceedingJoinPoint;
    @Aspect
    @Component
    public class LogAspect {
        /**
         * @Pointcut() 切入點表達式
         */
        @Pointcut("execution(* com.wener.example.aop.aspect.*.*(..))")
        public void logPointcut() {
        }
        /**
         * @AfterThrowing 異常通知 
         *   value:指定切入點表達式或命名切入點翔忽;
         *   throwing:異常類型。
         */
        @AfterThrowing("logPointcut()")
        public void afterThrowing() {
            System.out.println("異常通知");
        }
        /**
         * 如果想要限制通知只在某種特定的異常被拋出的時候匹配盏檐,同時還想知道異常的一些信息歇式。 
         * 那我們就需要使用throwing屬性聲明響應
         */
     @AfterThrowing(value = "logPointcut()", throwing = "exception")
        public void afterThrowing(Exception exception) {
            System.out.println("異常通知");
        }
    }
    

4.6、環(huán)繞通知

  1. 說明
    環(huán)繞通知在一個方法執(zhí)行之前和之后執(zhí)行胡野。它使得通知有機會 在一個方法執(zhí)行之前和執(zhí)行之后運行材失。而且它可以決定這個方法在什么時候執(zhí)行,如何執(zhí)行硫豆,甚至是否執(zhí)行龙巨。 環(huán)繞通知經(jīng)常在某線程安全的環(huán)境下,你需要在一個方法執(zhí)行之前和之后共享某種狀態(tài)的時候使用熊响。 請盡量使用最簡單的滿足你需求的通知旨别。(比如如果簡單的前置通知也可以適用的情況下不要使用環(huán)繞通知)。
    • 使用@Around注解汗茄;
    • 環(huán)繞通知需要攜帶ProceedingJoinPoint類型的參數(shù)秸弛;
    • 且環(huán)繞通知必須有返回值,返回值即為有目標方法的返回值剔难。
  2. 語法格式
    @Around(value = "", argNames = "")
    
  3. 參數(shù)
    • value :指定切入點表達式或切入點名字胆屿;
    • **argNames: **用來接收AspectJ表達式中的參數(shù),并指定通知方法中的參數(shù)
  4. 示例代碼
    import org.springframework.stereotype.Component;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.ProceedingJoinPoint;
    @Aspect
    @Component
    public class LogAspect {
        /**
         * @Pointcut() 切入點表達式
         */
        @Pointcut("execution(* com.wener.example.aop.aspect.*.*(..))")
        public void logPointcut() {
        }
        /**
         * @Around 環(huán)繞通知
         * 比如 緩存切面,如果緩存中有值偶宫,就返回該值非迹,否則調(diào)用proceed()方法
         * value:指定切入點表達式或命名切入點;
         * 注意 第一個參數(shù)必須是 ProceedingJoinPoint對象 具體這個類的更多詳細使用看附錄:
         */
        @Around(value = "logPointcut()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("環(huán)繞通知1");
            Object obj = pjp.proceed();
            System.out.println("環(huán)繞通知2");
            return obj;
        }
    }
    

4.7纯趋、通知參數(shù)

  1. 說明
    若想要在通知方法獲取被通知方法的參數(shù)共有兩種方式:自動獲取憎兽、手動指定
    • 自動獲取參數(shù):通知類型可以通過參數(shù)JoinPoint或者 ProceedingJoinPoint 自動獲取被通知方法的參數(shù)值并調(diào)用該方法
    • 手動指定參數(shù):即在配置切面時冷离,需在切面的通知與切面的切點中明確指定參數(shù)。
  2. 手動指定
    • 在@pointcut中切入表達式中使用args聲明匹配的參數(shù),注意使用&&連接args
    • 在@pointcut中切入表達式中使用參數(shù)argNames用來接收AspectJ表達式中的參數(shù)纯命,
      argNames屬性是用于指定在表達式中應用的參數(shù)名與Advice方法參數(shù)是如何對應的
    • 在通知方法中定義參數(shù)
  3. 手動獲取指定參數(shù)
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    @Aspect
    @Component
    public class LogAdviceParamsAspect {
     // 注意參數(shù)的個數(shù)必須一致,否則匹配不到
        @Before(value = "execution(* com.wener.example.aop.aspect.*.*(..))&& args(id,name)", argNames = "id,name")
        public void testArgs(Object id, Object name) {
            System.out.println(id);
            System.out.println(name);
        }
    }
    
  4. 混用使用
    當同時采用自動獲取參數(shù)與手動指定參數(shù)時西剥,自動獲取參數(shù)必須是第一個參數(shù),即ProceedingJoinPoint 等參數(shù)并需是通知方法定義的第一個參數(shù)
    import org.aopalliance.intercept.Joinpoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    @Aspect
    @Component
    public class LogAdviceParamsAspect {
      // args亿汞、argNames的參數(shù)名與testArgs()方法中參數(shù)名 保持一致
        @Before(value = "execution(* com.wener.example.aop.aspect.*.*(..))&& args(id,name)", argNames = "id,name")
        public void testArgs(Object id, Object name) {
            System.out.println(id);
            System.out.println(name);
        }
     // 也可以不用argNames
        @Before(value = "execution(* com.wener.example.aop.aspect.*.*(..))&& args(id,name)")
        public void testArgs(Object id, Object name) {
            System.out.println(id);
            System.out.println(name);
        }
        @Around(value = "execution(* com.wener.example.aop.aspect.*.*(..))&&(args(id,name,..))", argNames = "pjp,id,name")
        public Object testAroundArgs(ProceedingJoinPoint pjp, Object id, Object name) throws Throwable {
            System.out.println("Around之前");
            Object obj = pjp.proceed();
            System.out.println();
            return obj;
        }
    }
    

4.8 瞭空、引入

  1. 說明
    有時候有一組共享公共行為類。在OOP中疗我,它們必須擴展相同的基類或者實現(xiàn)相同的接口咆畏。此外,Java的單繼承機制僅允許一個類最多擴展一個基類吴裤。所以旧找,不能同時從多個實現(xiàn)類中繼承行為。
    解決方案:引入是AOP中的一種特殊的通知麦牺。它允許為一個接口提供實現(xiàn)類钮蛛,使對象動態(tài)的實現(xiàn)接口。就像對象在運行時擴展了實現(xiàn)類剖膳。而且魏颓,可以用多個實現(xiàn)類將多個接口同時引入對象。這可以實現(xiàn)與多重繼承相同的效果潮秘。
  2. 在開發(fā)中用的不是很多,所以不做過多的分析

5琼开、聲明代理類

  1. 說明
    被代理的對象,跟前面說的一樣,代理接口或者類都可以
  2. 示例代碼
    public interface AspectDao {
        public void test();
        public void testParams(int id, String name);
        public void testParams(Joinpoint jp, int id, String name);
    }
    @Component("aspectDao")
    public class AspectDaoImpl implements AspectDao {
        @Override
        public void test() {
            System.out.println("核心測試方法");
        }
        @Override
        public void testParams(int id, String name) {
            System.out.println("帶參數(shù)的方法:" + "ID:" + id + "name:" + name);
        }
    }
    

6、測試

  1. 示例代碼
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-aspect.xml");
    AspectDao dao = (AspectDao) context.getBean("aspectDao");
    dao.test();
    dao.testParams(1,"hello");
    

7枕荞、總結

  1. 使用@Aspect將POJO聲明為切面柜候;
  2. 在切面類中使用@Pointcut進行命名切入點聲明;
  3. 定義通知方法,使用5中注解聲明躏精,其中value用于定義切入點表達式或引用命名切入點渣刷;
  4. 配置文件需要使用<aop:aspectj-autoproxy/>來開啟注解風格的@AspectJ支持;
  5. 將切面類和POJO類注冊到Spring容器中

七矗烛、基于xml的AOP編程(掌握)

1辅柴、說明

如果比較喜歡使用XML格式,Spring2.0也提供了使用新的"aop"命名空間來定義一個切面瞭吃。 和使用@AspectJ風格完全一樣碌嘀,切入點表達式和通知類型同樣得到了支持

AOP配置元素 用途
<aop:config> 頂層的AOP配置元素,大多數(shù)的<aop:*>必須包含在<aop:config>元素內(nèi)
<aop:aspect> 定義一個切面
<aop:pointcut> 定義一個切點
<aop:advisor> 定義AOP通知器
<aop:before> 定義AOP前置通知
<aop:around> 定義AOP環(huán)繞通知
<aop:after-returning> 定義AOP返回通知
<aop:after-throwing> 定義AOP異常通知
<aop:after> 定義AOP后置通知(不管被通知的方法是否執(zhí)行成功)
<aop:aspectj-autoproxy> 啟用@Aspect注解的切面
<aop:declare-parents> 以透明的方式為被通知的對象引入額外的接口

2、引入aop命名空間標簽

  1. 說明
    在beans元素下 引入aop歪架,聲明<aop-config>股冗,在配置文件中,我們可以聲明多個<aop-config>和蚪。
    注意:
    • 所有的切面和通知都必須定義在<aop:config>元素內(nèi)部。
    • 一個<aop:config>可以包含pointcut,advisor和aspect元素 (注意這三個元素必須按照這個順序進行聲明)
  2. 示例代碼
    <beans
           ...
           xmlns:aop="http://www.springframework.org/schema/aop">
       ...
       <aop:config>
       </aop:config>
    </beans>
    

3掸冤、聲明一個切面

  1. 說明
    切面使用<aop:aspect>來聲明
  2. 示例代碼
    <aop:config>
      <aop:aspect id="myAspect" ref="myBean">
        ...
      </aop:aspect>
    </aop:config>
    <bean id="myBean" class="...">
      ...
    </bean>
    

4、聲明一個切入點

  1. 說明
    一個命名切入點可以在<aop:config>元素中定義浆洗,使用<aop:pointcut>聲明,這樣多個切面和通知就可以共享該切入點集峦,你也可以在切面中定義
  2. 示例代碼
    <aop:config>
      <aop:pointcut id="servicePointcut" 
            expression="execution(* *.*(..))"/>
    </aop:config>
    
    <aop:config>
      <aop:aspect id="myAspect" ref="myBean">
          <!--這個切入點只能在該 切面中使用  -->
         <aop:pointcut id="servicePointcut" 
            expression="execution(* *.*(..))"/>
      </aop:aspect>
    </aop:config>
    

5伏社、聲明通知

5.1、說明

和@AspectJ風格一樣少梁,基于xml的風格也支持5種通知類型并且兩者具有同樣的語義

5.2洛口、前置通知

  1. 說明
    前置通知在匹配方法執(zhí)行前運行。在<aop:aspect>中使用<aop:before> 元素來聲明它
  2. 示例代碼
    <aop:config>
      <aop:pointcut id="servicePointcut" 
            expression="execution(* *.*(..))"/>
      <aop:aspect id="beforeExample" ref="myBean">
         <aop:before 
              pointcut-ref="servicePointcut" 
              method="doBefore"/>
     </aop:aspect>     
    </aop:config>
    

5.3凯沪、后置通知

  1. 說明
    后置通知在匹配的方法完全執(zhí)行后運行。和前置通知一樣买优,在<aop:aspect> 里面使用<aop:after-returning>聲明妨马,通知方法可以得到返回值。使用returning屬性來指定傳遞返回值的參數(shù)名杀赢。
  2. 示例代碼
    <aop:aspect id="afterReturningExample" ref="myBean">
        <aop:after-returning 
          pointcut-ref="servicePointcut" 
          method="doAfterReturning"/>
        ...
    </aop:aspect>
    
    <aop:aspect id="afterReturningExample" ref="myBean">
        <aop:after-returning 
          pointcut-ref="servicePointcut" 
          method="doAfterReturning"/>
        ...
    </aop:aspect>
    

?

5.4烘跺、異常通知

  1. 說明
    異常通知在匹配方法拋出異常退出時執(zhí)行。在<aop:aspect>中使用 <after-throwing>元素來聲明脂崔,還可以使用throwing屬性來指定傳遞異常的參數(shù)名
  2. 示例代碼
    <!-- 無返回值 -->
    <aop:aspect id="afterThrowingExample" ref="myBean">
        <aop:after-throwing
          pointcut-ref="servicePointcut" 
          throwing="exception" 
          method="doAfterThrowing"/>
        ...
    </aop:aspect>
    

5.5滤淳、最終通知

  1. 說明
    最終通知無論如何都會在匹配方法退出后執(zhí)行。在<aop:aspect>中使用<aop:after>元素來聲明
  2. 示例代碼
    <aop:aspect id="afterFinallyExample" ref="myBean">
        <aop:after
          pointcut-ref="servicePointcut" 
          method="doAfter"/>
        ...
    </aop:aspect>
    

5.6砌左、環(huán)繞通知

  1. 說明
    環(huán)繞通知在匹配方法運行期的“周圍”執(zhí)行脖咐。 它有機會在目標方法的前面和后面執(zhí)行,并決定什么時候運行汇歹,怎么運行屁擅,甚至是否運行。環(huán)繞通知經(jīng)常在需要在一個方法執(zhí)行前后共享狀態(tài)信息产弹,并且是在線程安全的情況下使用
  2. 示例代碼
    <aop:aspect id="aroundExample" ref="myBean">
        <aop:around
          pointcut-ref="servicePointcut" 
          method="doAround"/>
        ...
    </aop:aspect>
    

八派歌、切面的優(yōu)先級

1、說明

在同一個連接點上應用不止一個切面時, 除非明確指定, 否則它們的優(yōu)先級是不確定的

  • 切面的優(yōu)先級可以通過實現(xiàn) Ordered 接口或利用 @Order 注解指定.
    實現(xiàn) Ordered 接口, getOrder() 方法的返回值越小, 優(yōu)先級越高.

  • 若使用 @Order 注解, 序號出現(xiàn)在注解中痰哨,值越小優(yōu)先級越高

2胶果、示例代碼

  1. 基于實現(xiàn)接口(了解)
    @Aspect
    @Component
    public class LoggingAspect implements Ordered {
        @Override
        public int getOrder() {
            return 2;
        }
    }
    
    @Aspect
    @Component
    public class ValidateAspect implements Ordered {
        @Override
        public int getOrder() {
            return 1;
        }
    }
    
  2. 基于注解
    @Order(2)
    @Aspect
    @Component
    public class LoggingAspect {
    }
    
    @Order(1)
    @Aspect
    @Component
    public class ValidateAspect {
    }
    

九、簡單總結

  1. 切面的內(nèi)容可以復用
  2. 避免使用Proxy斤斧、CGLIB生成代理早抠,這方面的工作全部框架去實現(xiàn),開發(fā)者可以專注于切面內(nèi)容本身
  3. 代碼與代碼之間沒有耦合折欠,如果攔截的方法有變化修改配置文件即可

十贝或、附錄

1吼过、獲取目標對象信息

1.1、JoinPoint 對象

  1. 說明
    JoinPoint對象封裝了SpringAop中切面方法的信息,在切面方法中添加JoinPoint參數(shù),就可以獲取到封裝了該方法信息的JoinPoint對象
  2. 重要方法
    方法 說明
    Signature getSignature(); 獲取封裝了署名信息的對象,在該對象中可以獲取到目標方法名,所屬類的Class等信息
    Object[] getArgs(); 獲取連接點方法運行時的入?yún)⒘斜?/strong>
    Object getTarget(); 獲取連接點所在的目標對象
    Object getThis(); 獲取代理對象本身

1.2咪奖、ProceedingJoinPoint

  1. 說明
    ProceedingJoinPoint繼承JoinPoint子接口盗忱,并且只能用于@Around的切面方法中
  2. 新增方法
    方法名 功能
    Object proceed() throws Throwable 執(zhí)行目標方法
    Object proceed(Object[] var1) throws Throwable 傳入的新的參數(shù)去執(zhí)行目標方法

1.2、示例代碼

  1. 案例1
    Aspect
    @Component
    public class JoinPointerAspect {
        /**
         * 定義一個切入點表達式,用來確定哪些類需要代理
         */
        @Pointcut("execution(* com.wener.example.aop.aspect.*.*(..))") 
        public void declareJoinPointer() {}
        /**
         * 前置方法,在目標方法執(zhí)行前執(zhí)行
         * @param joinPoint 封裝了代理方法信息的對象,若用不到則可以忽略不寫
         */
        @Before("declareJoinPointer()")
        public void beforeMethod(JoinPoint joinPoint){
            System.out.println("目標方法名:" + joinPoint.getSignature().getName());
            System.out.println("目標方法所屬類的名:" +        joinPoint.getSignature().getDeclaringType().getSimpleName());
            System.out.println("目標方法聲明類型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
            //獲取傳入目標方法的參數(shù)
            Object[] args = joinPoint.getArgs();
            for (int i = 0; i < args.length; i++) {
                System.out.println("第" + (i+1) + "個參數(shù)為:" + args[i]);
            }
            System.out.println("被代理的對象:" + joinPoint.getTarget());
            System.out.println("代理對象自己:" + joinPoint.getThis());
        }
        /**
         * 環(huán)繞方法,可自定義目標方法執(zhí)行的時機
         * @param pjd JoinPoint的子接口,添加了
         *  Object proceed() throws Throwable 執(zhí)行目標方法
         *  Object proceed(Object[] var1) throws Throwable 傳入的新的參數(shù)去執(zhí)行目標方法
         *         
         * @return 此方法需要返回值,返回值視為目標方法的返回值
         */
        @Around("declareJoinPointer()")
        public Object aroundMethod(ProceedingJoinPoint pjd){
            Object result = null;
            try {
                //前置通知
                System.out.println("目標方法執(zhí)行前...");
                //執(zhí)行目標方法
                //result = pjd.proeed();
                //用新的參數(shù)值執(zhí)行目標方法
                result = pjd.proceed(new Object[]{"hello","world"});
                //返回通知
                System.out.println("目標方法返回結果后...");
            } catch (Throwable e) {
                //異常通知
                System.out.println("執(zhí)行目標方法異常后...");
                throw new RuntimeException(e);
            }
            //后置通知
            System.out.println("目標方法執(zhí)行后...");
            return result;
        }
    }
    
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末羊赵,一起剝皮案震驚了整個濱河市趟佃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌昧捷,老刑警劉巖闲昭,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異靡挥,居然都是意外死亡序矩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門跋破,熙熙樓的掌柜王于貴愁眉苦臉地迎上來簸淀,“玉大人,你說我怎么就攤上這事毒返∽饽唬” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵拧簸,是天一觀的道長劲绪。 經(jīng)常有香客問我,道長盆赤,這世上最難降的妖魔是什么贾富? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮弟劲,結果婚禮上祷安,老公的妹妹穿的比我還像新娘。我一直安慰自己兔乞,他們只是感情好汇鞭,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著庸追,像睡著了一般霍骄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上淡溯,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天读整,我揣著相機與錄音,去河邊找鬼咱娶。 笑死米间,一個胖子當著我的面吹牛强品,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屈糊,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼的榛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了逻锐?” 一聲冷哼從身側響起夫晌,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎昧诱,沒想到半個月后晓淀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡盏档,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年凶掰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妆丘。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡锄俄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出勺拣,到底是詐尸還是另有隱情,我是刑警寧澤鱼填,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布药有,位于F島的核電站,受9級特大地震影響苹丸,放射性物質(zhì)發(fā)生泄漏愤惰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一赘理、第九天 我趴在偏房一處隱蔽的房頂上張望宦言。 院中可真熱鬧,春花似錦商模、人聲如沸奠旺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽响疚。三九已至,卻和暖如春瞪醋,著一層夾襖步出監(jiān)牢的瞬間忿晕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工银受, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留践盼,地道東北人鸦采。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像咕幻,于是被迫代替她去往敵國和親渔伯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容

  • 上一篇:Spring學習筆記(七、Spring AOP API) 一绷耍、AspectJ介紹與Pointcut注解應用...
    魯克巴克詩閱讀 3,906評論 0 4
  • IoC 容器 Bean 的作用域 自定義作用域實現(xiàn) org.springframework.beans.facto...
    Hsinwong閱讀 2,476評論 0 7
  • 最近開發(fā)中有一個需求,要求對指定的操作進行日志管理褂始,以備以后查驗诸典。為了在保全大部分代碼結構的前提下,選擇了面向切面...
    此處應該有一個名字閱讀 720評論 0 1
  • 1.Aspect用戶行為統(tǒng)計 他不生成代碼崎苗,他是生產(chǎn)的搬運工去做行為統(tǒng)計 AOP切面編程 在AOP術語體系中狐粱,切面...
    waterge閱讀 430評論 0 0
  • 一、AOP的基礎 1.1胆数、AOP是什么肌蜻??必尼? 考慮這樣一個問題:需要對系統(tǒng)中的某些業(yè)務做日志記錄蒋搜,比如支付系統(tǒng)中的...
    聶叼叼閱讀 2,117評論 2 17