AOP系列(二) Spring AOP

1、簡介

Spring AOP 提供全面的 AOP 解決方案。Spring 將 Spring AOP 和 IOC 與 AspectJ 無縫集成,以便在一致的 Spring-based application architecture 中知足 AOP 的全部使用需求。java

2、SpringBoot集成Spring-Aop

添加依賴

maven依賴添加以下
<!--引入SpringBoot的Web模塊-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
 
<!--引入AOP依賴-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
複製代碼

注意:在完成了引入AOP依賴包後,不須要去作其餘配置。AOP的默認配置屬性中,spring.aop.auto屬性默認是開啓的,也就是說只要引入了AOP依賴後,默認已經增長了@EnableAspectJAutoProxy,不須要在程序主類中增長@EnableAspectJAutoProxy來啓用。web

編寫切面代碼

切面類使用@Aspect標註,必須加 @Component,使得切面類注入IOC容器管理spring

@Aspect
@Component
@Slf4j
public class TestLog {


@Pointcut("execution(* com.yuntian.example.controller.*.*(..))")
public void testLog() {
}


/**
 * 前置通知,方法執行以前執行
 * @param jp
 */
@Before("testLog()")
public void doBefore(JoinPoint jp) {
    // ...
    log.info("方法執行前:.............");
}

/**
 * 後置通知,方法執行以後執行(無論是否發生異常)
 * @param jp
 */
@After("testLog()")
public void doAfter(JoinPoint jp) {
    // ...
    log.info("方法執行後:.............");
}


/**
 * 返回通知,方法正常執行完畢以後執行
 * @param jp
 */
@AfterReturning("testLog()")
public void doAfterReturning(JoinPoint jp) {
    // ...
    log.info("方法執行後返回通知:.............");
}

/**
 * 異常通知,在方法拋出異常以後執行
 * @param jp
 * @param e
 */
@AfterThrowing(value="testLog()",throwing="e")
public void doAfterThrowing(JoinPoint jp,Exception e) {
    // ...
    log.info("方法執行後異常:.............");
}

}
複製代碼

業務代碼

package com.yuntian.example.controller;

import com.yuntian.example.base.Result;
import com.yuntian.example.entity.dto.OrderDTO;
import com.yuntian.example.entity.vo.OrderVO;
import com.yuntian.example.service.OrderService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author yuntian.
 * @date Created in 18:13 2019/8/7
 * @description
 */
@RestController
@RequestMapping("order")
public class OrderController {


@Resource
private OrderService orderService;


@PostMapping("/createOrder")
public Result createOrder(OrderDTO dto){
   OrderVO orderVO= orderService.createOrder(dto);
    Result<OrderVO> result=new Result<>();
    result.setData(orderVO);
    result.setCode(99);
    return result;
}
}
複製代碼

結果app

能夠看到切面類,實現邏輯同時,而對業務代碼毫無侵入。maven

編寫切面代碼,使用環繞通知

@Aspect
@Component
@Slf4j
public class TestLogAround {


@Pointcut("execution(* com.yuntian.example.controller.*.*(..))")
public void testLogAround() {
}

/**
 * 使用環繞通知
 * @param pjp
 * @return
 */
@Around("testLogAround()")
public Object doAround(ProceedingJoinPoint pjp){
    Object obj=null;
    try{
        log.info("前置通知:執行以前");
        obj=pjp.proceed();
        log.info("返回通知:執行以後");
    } catch(Throwable e){
        log.info("異常通知:........!");
    }
    return  obj;
}
}
複製代碼

結果spring-boot

編寫切面代碼,配合自定義註解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MTransaction {

@AliasFor("transactionManager")
String value() default "";

@AliasFor("value")
String transactionManager() default "";


int timeout() default -1;

boolean readOnly() default false;

Class<? extends Throwable>[] rollbackFor() default {};

String[] rollbackForClassName() default {};

Class<? extends Throwable>[] noRollbackFor() default {};

String[] noRollbackForClassName() default {};
}



@Component
@Slf4j
@Aspect
public class TransactionAspect {

@Pointcut("@annotation(com.yuntian.example.annotation.MTransaction)")
public void transactionAspect() {
}

/**
 * 使用環繞通知
 *
 * @param pjp
 * @return
 */
@Around("transactionAspect()")
public Object doAround(ProceedingJoinPoint pjp) {
    //得到執行方法的類名
    MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
    Method method = methodSignature.getMethod();
    Object[] args= pjp.getArgs();
    Object obj = null;
    try {
        log.info("前置通知:開啓事務...");
        MTransaction transaction = method.getAnnotation(MTransaction.class);
        if (transaction != null) {
            log.info("註解信息:" + transaction.value());
        }
        log.info("參數:"+JSON.toJSONString(args));
        obj = pjp.proceed();
        log.info("返回通知:關閉事務...");
    } catch (Throwable e) {
        log.info("異常通知:事務回滾...");
    }
    return obj;
}

}
複製代碼

結果this

2、切面介紹

切點表達式

切入點是範圍內的全部類的方法spa

@Pointcut("execution(* com.yuntian.example.controller.*.*(..))")
複製代碼

切入點是註解的方法.net

@Pointcut("@annotation(com.yuntian.example.annotation.MTransaction)")
複製代碼

AspectJ指示器

指示器 描述
arg() 限制鏈接點匹配參數爲指定類型的執行方法
@args() 限制鏈接點匹配參數爲指定註解標註的執行方法
execution() 用於匹配是鏈接點的執行方法
this() 限制鏈接點匹配參數爲指定註解標註的執行方法
target 限制鏈接點匹配目標對象爲指定類型的類
within() 限制鏈接點匹配指定的類型
@within() 限制鏈接點匹配指定註解鎖標註的類型(當使用Spring Aop時,方法定義由指定的註解所標註的類)
@annotation 限制匹配帶有指定註解的鏈接點

JoinPoint用法

4、參考資料

blog.csdn.net/XU906722/ar…code

相關文章
相關標籤/搜索