<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Spring基于注解實現 AOP 切面功能

      前言

      在Spring AOP(Aspect-Oriented Programming)中,動態代理是常用的技術之一,用于在運行時動態地為目標對象生成代理對象,
      并攔截其方法調用。Spring AOP 默認使用兩種類型的動態代理機制:JDK 動態代理和 CGLIB 代理。 ?JDK 動態代理?: JDK 動態代理是 Java 原生提供的動態代理機制,它只能代理接口。如果你的目標對象實現了某個接口,Spring AOP 會默認使用 JDK 動態代理。 JDK 動態代理機制通過 java.lang.reflect.Proxy 類來創建代理對象,并將方法調用委托給 InvocationHandler 實現。 ?CGLIB 代理?: 如果目標對象沒有實現接口,Spring AOP 會使用 CGLIB(Code Generation Library)來生成代理對象。CGLIB 是一個強大的庫,
      可以生成目標對象的子類,并覆蓋其方法以實現代理功能。通過 CGLIB,Spring AOP 能夠代理沒有實現接口的類(即具體的類)。 默認代理機制的選擇 Spring AOP 在選擇使用哪種代理機制時,遵循以下原則: 如果目標對象實現了至少一個接口,則默認使用 JDK 動態代理。 如果目標對象沒有實現任何接口,則默認使用 CGLIB 代理。 配置示例 在大多數情況下,你不需要顯式地指定使用哪種代理機制,因為 Spring 會自動為你選擇。但是,如果你有特殊需求,可以通過配置來強制使用某種代理機制。

      一、Spring AOP 注解概述

      1.Spring 的 AOP 功能除了在配置文件中配置一大堆的配置,比如切入點、表達式、通知等等以外,
      使用注解的方式更為方便快捷,特別是 Spring boot 出現以后,基本不再使用原先的 beans.xml 等配置文件了,而都推薦注解編程

      @Aspect 切面聲明,標注在類、接口(包括注解類型)或枚舉上。
      @Pointcut

      切入點聲明,即切入到哪些目標類的目標方法。既可以用 execution 切點表達式, 也可以是 annotation 指定攔截擁有指定注解的方法.

      value 屬性指定切入點表達式,默認為 "",用于被通知注解引用,這樣通知注解只需要關聯此切入點聲明即可,無需再重復寫切入點表達式

      @Before

      前置通知, 在目標方法(切入點)執行之前執行。

      value 屬性綁定通知的切入點表達式,可以關聯切入點聲明,也可以直接設置切入點表達式

      注意:如果在此回調方法中拋出異常,則目標方法不會再執行,會繼續執行后置通知 -> 異常通知。

      @After 后置通知, 在目標方法(切入點)執行之后執行
      @AfterReturning

      返回通知, 在目標方法(切入點)返回結果之后執行.

      pointcut 屬性綁定通知的切入點表達式,優先級高于 value,默認為 ""

      @AfterThrowing

      異常通知, 在方法拋出異常之后執行, 意味著跳過返回通知

      pointcut 屬性綁定通知的切入點表達式,優先級高于 value,默認為 ""

      注意:如果目標方法自己 try-catch 了異常,而沒有繼續往外拋,則不會進入此回調函數

      @Around

      環繞通知:目標方法執行前后分別執行一些代碼,類似攔截器,可以控制目標方法是否繼續執行。

      通常用于統計方法耗時,參數校驗等等操作。

      2、上面這些 AOP 注解都是位于 aspectjweaver 依賴中;對于習慣了 Spring 全家桶編程的人來說,并不是需要直接引入 aspectjweaver 依賴,因為 spring-boot-starter-aop 組件默認已經引用了 aspectjweaver 來實現 AOP 功能。換句話說 Spring 的 AOP 功能就是依賴的 aspectjweaver !

      <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-aop</artifactId>
          <version>2.1.4.RELEASE</version>
      </dependency>

      3.AOP 底層是通過 Spring 提供的的動態代理技術實現的,在運行期間動態生成代理對象,代理對象方法執行時進行增強功能的介入,再去調用目標對象的方法,從而完成功能的增強。主要使用 JDK 動態代理與 Cglib 動態代理;所以如果目標類不是 Spring 組件,則無法攔截,如果是 類名.方法名 方式調用,也無法攔截。

      二、@Aspect 快速入門

      1、@Aspect 常見用于記錄日志、異常集中處理、權限驗證、Web 參數校驗、事務處理等等
      
      2、要想把一個類變成切面類,只需3步:
      
        1)在類上使用 @Aspect 注解使之成為切面類
      
        2)切面類需要交由 Spring 容器管理,所以類上還需要有 @Service、
           @Repository、@Controller、@Component 等注解
        2)在切面類中自定義方法接收通知
      
      3、AOP 的含義就不再累述了,下面直接上示例:
      /**
       * 切面類,用于處理日志、參數校驗等
       *
       * @author songwp
       * @date 2020-04-27
       */
      @Aspect
      @Component
      @Slf4j
      public class HandleAspect {
      
          /**
           * @Pointcut :切入點聲明,即切入到哪些目標方法。value 屬性指定切入點表達式,默認為 ""。
           * 用于被下面的通知注解引用,這樣通知注解只需要關聯此切入點聲明即可,無需再重復寫切入點表達式
           * <p>
           * 切入點表達式常用格式舉例如下:
           * - * com.songwp.aspect.EmpService.*(..)):表示 com.songwp.aspect.EmpService 類中的任意方法
           * - * com.songwp.aspect.*.*(..)):表示 com.songwp.aspect 包(不含子包)下任意類中的任意方法
           * - * com.songwp.aspect..*.*(..)):表示 com.songwp.aspect 包及其子包下任意類中的任意方法
           * </p>
           * value 的 execution 可以有多個,使用 || 隔開.
           */
          @Pointcut("execution(public * com.songwp.controller.*.*(..))")
          public void aopPointCut() {}
      
      
          /**
           * 前置通知:目標方法執行之前執行以下方法體的內容。
           * value:綁定通知的切入點表達式。可以關聯切入點聲明,也可以直接設置切入點表達式
           * <br/>
           * * @param joinPoint:提供對連接點處可用狀態和有關它的靜態信息的反射訪問<br/> <p>
           * * * Object[] getArgs():返回此連接點處(目標方法)的參數,目標方法無參數時,返回空數組
           * * * Signature getSignature():返回連接點處的簽名。
           * * * Object getTarget():返回目標對象
           * * * Object getThis():返回當前正在執行的對象
           * * * StaticPart getStaticPart():返回一個封裝此連接點的靜態部分的對象。
           * * * SourceLocation getSourceLocation():返回與連接點對應的源位置
           * * * String toLongString():返回連接點的擴展字符串表示形式。
           * * * String toShortString():返回連接點的縮寫字符串表示形式。
           * * * String getKind():返回表示連接點類型的字符串
           * * * </p>
           */
          @Before("aopPointCut()")
          public void beforeAdvice() {
              System.out.println("前置通知執行");
          }
      
          /**
           * 后置通知:目標方法執行之后執行以下方法體的內容,不管目標方法是否發生異常。
           * value:綁定通知的切入點表達式。可以關聯切入點聲明,也可以直接設置切入點表達式
           */
          @After("aopPointCut()")
          public void afterAdvice() {
              System.out.println("后置通知執行");
          }
      
          /**
           * 返回通知:目標方法返回后執行以下代碼
           * value 屬性:綁定通知的切入點表達式。可以關聯切入點聲明,也可以直接設置切入點表達式
           * pointcut 屬性:綁定通知的切入點表達式,優先級高于 value,默認為 ""
           * returning 屬性:通知簽名中要將返回值綁定到的參數的名稱,默認為 ""
           *
           * @param joinPoint :提供對連接點處可用狀態和有關它的靜態信息的反射訪問
           */
          @AfterReturning("execution(* com.songwp.service.impl.OperateLogServiceImpl.*(..))")
          public void logAfterReturning(JoinPoint joinPoint) {
              System.out.println("返回后通知: " + joinPoint.getSignature().getName());
          }
      
          /**
           * 異常通知:目標方法發生異常的時候執行以下代碼,此時返回通知不會再觸發
           * value 屬性:綁定通知的切入點表達式。可以關聯切入點聲明,也可以直接設置切入點表達式
           * pointcut 屬性:綁定通知的切入點表達式,優先級高于 value,默認為 ""
           * throwing 屬性:與方法中的異常參數名稱一致,
           *
           * @param ex:捕獲的異常對象,名稱與 throwing 屬性值一致
           */
          @AfterThrowing(pointcut = "execution(* com.songwp.service.impl.OperateLogServiceImpl.*(..))", throwing = "ex")
          public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {
              System.out.println("異常后通知: " + joinPoint.getSignature().getName() + ", Exception: " + ex);
          }
      
          /**
           * 環繞通知
           * 1、@Around 的 value 屬性:綁定通知的切入點表達式。可以關聯切入點聲明,也可以直接設置切入點表達式
           * 2、Object ProceedingJoinPoint.proceed(Object[] args) 方法:繼續下一個通知或目標方法調用,返回處理結果,如果目標方法發生異常,則 proceed 會拋異常.
           * 3、假如目標方法是控制層接口,則本方法的異常捕獲與否都不會影響目標方法的事務回滾
           * 4、假如目標方法是控制層接口,本方法 try-catch 了異常后沒有繼續往外拋,則全局異常處理 @RestControllerAdvice 中不會再觸發
           *
           * @param joinPoint
           * @return
           * @throws Throwable
           */
          @Around("execution(* com.songwp.service.impl.OperateLogServiceImpl.*(..))")
          public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
              this.checkRequestParam(joinPoint);
              System.out.println("環繞通知: " + joinPoint.getSignature().getName());
              // 繼續執行方法
              Object result = joinPoint.proceed();
              System.out.println("環繞通知: " + joinPoint.getSignature().getName());
              return result;
          }
      
          /**
           * 參數校驗,防止 SQL 注入
           *
           * @param joinPoint
           */
          private void checkRequestParam(ProceedingJoinPoint joinPoint) {
              Object[] args = joinPoint.getArgs();
              if (args == null || args.length <= 0) {
                  return;
              }
              String params = Arrays.toString(joinPoint.getArgs()).toUpperCase();
              String[] keywords = {"DELETE ", "UPDATE ", "SELECT ", "INSERT ", "SET ", "SUBSTR(", "COUNT(", "DROP ",
                      "TRUNCATE ", "INTO ", "DECLARE ", "EXEC ", "EXECUTE ", " AND ", " OR ", "--"};
              for (String keyword : keywords) {
                  if (params.contains(keyword)) {
                      log.error("參數存在SQL注入風險,其中包含非法字符 {}.", keyword);
                      throw new RuntimeException("參數存在SQL注入風險:params=" + params);
                  }
              }
          }
      }

      三、@Aspect 切面不生效原因

      確保切面類被Spring管理?:在切面類上添加 @Service、@Repository、@Controller、@Component  等注解
      檢查路徑設置?:確保切面類被 @ComponentScan 注解掃描到。即有沒有被Spring容器管理。可以使用 @PostConstruct注解測試。
      檢查切面表達式?:確保切面表達式正確無誤,能夠匹配到目標方法。

      特別注意: 比如定義了一個 AOP 切面(@Pointcut)攔截 ServiceA 中的方法 B,當從其他類調用方法 B 時(比如 Controller 層),會正常切入攔截,而從本類其他方法中調用方法 B 時,無法切入攔截,因為此時默認并不是通過代理對象調用的,而是直接通過 this 對象來調的。可以參考@EnableAspectJAutoProxy注解。

      總結:AOP的高級特性使得開發者能夠以聲明式的方式處理復雜的應用場景。通過靈活使用切入點表達式和正則表達式,可以在Spring AOP中實現精確的連接點匹配。此外,AOP在性能監控、日志記錄、事務管理等場景中的應用,展示了其在提高代碼模塊化和可維護性方面的強大能力。

      posted @ 2024-12-02 11:27  [奮斗]  閱讀(571)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 99久久精品国产熟女拳交| 成人欧美日韩一区二区三区| 精品国产片一区二区三区| 亚洲+成人+国产| 国产综合色在线精品| 99精品视频在线观看免费蜜桃| 亚洲一区二区精品另类| 四虎影视久久久免费| 日韩精品成人区中文字幕| 日本视频一区二区三区1| 免费a级毛片18以上观看精品| 西青区| 国产精品进线69影院| 人妻丝袜无码专区视频网站 | 亚洲AV成人片不卡无码| 40岁成熟女人牲交片20分钟| 中文字幕色av一区二区三区| 国产精品视频一品二区三| 国产va在线观看免费| 精品国产一区二区三区国产区 | 国产激情无码一区二区三区| 成人综合人人爽一区二区| 亚洲黄色性视频| 五月综合网亚洲乱妇久久| 麻豆国产黄色一级免费片| 制服丝袜长腿无码专区第一页| 亚洲精品成人片在线观看精品字幕| 妺妺窝人体色www婷婷| 免费无码黄十八禁网站| 丰宁| 国产极品尤物粉嫩在线观看| 福利一区二区1000| 久久久亚洲欧洲日产国码αv| 国产精品无码不卡在线播放| 亚洲最大av一区二区| 亚洲精中文字幕二区三区| 中文字幕永久精品国产| 亚洲天堂网中文在线资源| 在线免费播放av日韩| 在国产线视频A在线视频| 欧美人与动牲交a免费|