欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Springboot 中使用 Aop代碼實戰(zhàn)教程

 更新時間:2023年07月21日 14:44:16   作者:青銅愛碼士  
AOP的編程思想是把對類對象的橫切問題點,從業(yè)務邏輯中分離出來,從而達到解耦的目的,增加代碼的復用性,提高開發(fā)效率,這篇文章主要介紹了Springboot中使用Aop代碼實戰(zhàn)教程,需要的朋友可以參考下

1. aop作用

AOP意為面向切面編程,可以通過預編譯方式和運行期動態(tài)代理實現(xiàn)在不修改源代碼的情況下給程序動態(tài)統(tǒng)一添加功能的一種技術。AOP的編程思想是把對類對象的橫切問題點,從業(yè)務邏輯中分離出來,從而達到解耦的目的,增加代碼的復用性,提高開發(fā)效率。

2. 相關注解

@Component :將當前類注入到Spring容器內。
@Aspect :表明當前類是一個切面類。
@Before :前置通知,在被切入方法執(zhí)行之前執(zhí)行。
@After :后置通知,在被切入方法執(zhí)行之后執(zhí)行。
@AfterRuturning :返回通知,在被切入方法返回結果之后執(zhí)行。使用此注解的方法,可以使用returning = "XXX"返回被切入方法的返回值,XXX即為被切入方法的返回值,本例中是controller類中方法的返回值。

//返回通知
@AfterReturning(returning = "ret", pointcut = "log()")
public void doAfterReturning(Object ret) throws Throwable {
    // 處理完請求,返回內容
    System.out.println("返回通知:方法的返回值 : " + ret);
}

@AfterThrowing :異常通知,在被切入方法拋出異常之后執(zhí)行。在此注解中可以使用throwing = "XXX"獲取異常信息,獲取的異常信息可以在方法中打印出來,舉例如下。

/

/異常通知
@AfterThrowing(throwing = "ex", pointcut = "log()")
public void throwss(JoinPoint jp, Exception ex) {
    System.out.println("異常通知:方法異常時執(zhí)行.....");
    System.out.println("產生異常的方法:" + jp);
    System.out.println("異常種類:" + ex);
}

@Around :環(huán)繞通知,圍繞著被切入方法執(zhí)行。參數(shù)必須為ProceedingJoinPoint,pjp.proceed相應于執(zhí)行被切面的方法。環(huán)繞通知一般單獨使用,環(huán)繞通知可以替代上面的四種通知,后面單獨介紹。@Pointcut :切入點,PointCut(切入點)表達式有很多種,其中execution用于使用切面的連接點。

注意:返回通知和異常通知只能有一個會被執(zhí)行,因為發(fā)生異常執(zhí)行異常通知,然后就不會繼續(xù)向下執(zhí)行,自然后置通知也就不會被執(zhí)行,反之亦然。后置通知一定會執(zhí)行。

3. Aop 相關概念

Joinpoint(連接點):所謂連接點是指那些被攔截到的點,在 spring 中,這些點指的是方法,因為 spring 只支持方法類型的連接點,通俗的說就是被增強類中的所有方法。注意: 除了環(huán)繞通知外,其他的四個通知注解中,加或者不加參數(shù)JoinPoint都可以,如果有用到JoinPoint的地方就加,用不到就可以不加。JoinPoint里包含了類名、被切面的方法名,參數(shù)等屬性。PointCut(切入點):所謂切入點是指我們要對哪些 Joinpoint 進行攔截的定義,通俗的說就是被增強類中的被增強的方法,因為被增強類中并不是所有的方法都被增強了。Advice(通知/增強):所謂通知是指攔截到 Joinpoint (被增強的方法)之后所要做的事情就是通知,通俗的說就是對被增強的方法進行增強的代碼Aspect(切面):是切入點和通知(引介)的結合,通俗的說就是建立切入點和通知方法在創(chuàng)建時的對應關系。

4. 切入點表達式詳解:@PointCut(表達式)

PointCut:切入點,指哪些方法需要被執(zhí)行AOP,PointCut表達式可以有一下幾種方式:

1.execution表達式

表達式語法:訪問修飾符 返回值 包名.包名.包名…類名.方法名(參數(shù)列表)標準的表達式寫法范例:

public void com.aismall.testaop.controller.HelloController.helloAop()

訪問修飾符可以省略

void com.aismall.testaop.controller.HelloController.helloAop()

返回值可以使用通配符*,表示任意返回值

* com.aismall.testaop.controller.HelloController.helloAop()

包名可以使用通配符,表示任意包,但是有幾級包,就需要寫幾個*.

*  *.*.*.*.HelloController.helloAop()

包名可以使用…表示當前包及其子包

* *...HelloController.helloAop()

類名和方法名都可以使用*來實現(xiàn)通配

* *..*.*()

表達式中的參數(shù)列表,可以直接寫數(shù)據(jù)類型:

基本類型直接寫名稱 :例如,int
引用類型寫包名.類名的方式 :例如,java.lang.String
可以使用通配符表示任意類型,但是必須有參數(shù)
可以使用…表示有無參數(shù)均可,有參數(shù)可以是任意類型
全通配寫法: ….*(…)

2.within表達式是用來指定類型的,指定類型中的所有方法將被攔截表達式:包名.包名.包名…類名標準的表達式寫法范例:

com.aismall.testaop.controller.HelloController

舉例:匹配HelloController類對應對象的所有方法,并且只能是HelloController類生成的對象,不能是它的子類生成的對象。

within(com.aismall.testaop.controller.HelloController)

也可以使用通配符*:匹配com.aismall包及其子包下面的所有類的所有方法。

within(com.aismall…*)

3.this(type)

SpringAOP是基于代理的,this就代表代理對象,語法是this(type),當生成的代理對象可以轉化為type指定的類型時表示匹配。this(com.aismall.testaop.controller.HelloController)匹配生成的代理對象是HelloController類型的所有方法的外部調用

4.target

SpringAOP是基于代理的,target表示被代理的目標對象,當被代理的目標對象可以轉換為指定的類型時則表示匹配。target(com.aismall.testaop.controller.HelloController) 匹配所有被代理的目標對象能夠轉化成HelloController類型的所有方法的外部調用。

5.args:

args用來匹配方法參數(shù)
args() 匹配不帶參數(shù)的方法
args(java.lang.String) 匹配方法參數(shù)是String類型的
args(…) 帶任意參數(shù)的方法
args(java.lang.String,…) 匹配第一個參數(shù)是String類型的,其他參數(shù)任意。最后一個參數(shù)是String的同理。

6.@ annotation:帶有相應注解的方法,比如對標有@Transactional注解的方法進行增強

@annotation(org.springframework.transaction.annotation.Transactional)

@within和@target針對類的注解@annotation針對方法的注解@args:參數(shù)帶有相應標注的任意方法,比如@Transactional

@args(org.springframework.transaction.annotation.Transactional)

5. 代碼實戰(zhàn) 使用execution(表達式)

創(chuàng)建一個aspect切面類

@Aspect
@Component
public class MyAop {
    //切入點:待增強的方法
    @Pointcut("execution(public * com.xxx.controller.*.*(..))")
    //切入點簽名
    public void log(){
        System.out.println("pointCut簽名。。。");
    }
    //前置通知
    @Before("log()")
    public void deBefore(JoinPoint jp) throws Throwable {
        // 接收到請求,記錄請求內容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 記錄下請求內容
        System.out.println("URL : " + request.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + request.getMethod());
        System.out.println("CLASS_METHOD : " + jp);
        System.out.println("ARGS : " + Arrays.toString(jp.getArgs()));
    }
    //返回通知
    @AfterReturning(returning = "ret", pointcut = "log()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 處理完請求,返回內容
        System.out.println("返回通知:方法的返回值 : " + ret);`在這里插入代碼片`
    }
    //異常通知
    @AfterThrowing(throwing = "ex", pointcut = "log()")
    public void throwss(JoinPoint jp,Exception ex){
        System.out.println("異常通知:方法異常時執(zhí)行.....");
        System.out.println("產生異常的方法:"+jp);
        System.out.println("異常種類:"+ex);
    }
    //后置通知
    @After("log()")
    public void after(JoinPoint jp){
        System.out.println("后置通知:最后且一定執(zhí)行.....");
    }
}

創(chuàng)建controlle

@RestController
public class HelloController {
    @RequestMapping("/helloAop")
    public Object hello(){
        return "hello aop";
    }
    @RequestMapping("/helloError")
    public Object helloError(){
        return 1/0;
    }
}

測試

6. 代碼實戰(zhàn) 使用@annotation

自定義注解

//表示次注解可以標注在類和方法上
@Target({ElementType.METHOD, ElementType.TYPE})
//運行時生效
@Retention(RetentionPolicy.RUNTIME)
public @interface MyLogAnnotation {
    //定義一個變量,可以接受參數(shù)
    String desc() default " ";
}

切面類

@Aspect
@Component
public class MyAopAnnotation {
    //切入點:增強標有MyLogAnnotation注解的方法
    @Pointcut(value="@annotation(com.aismall.testaop.MyAnnotation.MyLogAnnotation)")
    //切入點簽名
    public void logAnnotation(){
        System.out.println("pointCut簽名。。。");
    }
    //前置通知
    @Before("logAnnotation()")
    public void deBefore(JoinPoint jp) throws Throwable {
        // 接收到請求,記錄請求內容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 記錄下請求內容
        System.out.println("URL : " + request.getRequestURL().toString());
    }
    //返回通知
    @AfterReturning(returning = "ret", pointcut = "logAnnotation()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 處理完請求,返回內容
        System.out.println("返回通知:方法的返回值 : " + ret);
    }
    //異常通知
    @AfterThrowing(throwing = "ex", pointcut = "logAnnotation()")
    public void throwss(JoinPoint jp,Exception ex){
        System.out.println("異常通知:方法異常時執(zhí)行.....");
        System.out.println("產生異常的方法:"+jp);
        System.out.println("異常種類:"+ex);
    }
    //后置通知
    @After("logAnnotation()")
    public void after(JoinPoint jp){
        System.out.println("后置通知:最后且一定執(zhí)行.....");
    }
}

Controller類

@RequestMapping("helloAnnotation")
//標有這個注解的方法會被增強
@MyLogAnnotation(desc = "@Annotation")
public Object helloAnnotation() {
    return "hello annotation";
}

到此這篇關于Springboot 中使用 Aop的文章就介紹到這了,更多相關Springboot使用 Aop內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論