官术网_书友最值得收藏!

3.1.2 Spring AOP案例分析

在理解了AOP的相關概念以及Spring框架所提供的各種注解之后,在本節中,我們將通過代碼示例來展示注解的使用方法。

現在,假設有一個代表用戶賬戶的AccountService接口,如代碼清單3-1所示。

代碼清單3-1 AccountService接口代碼

public interface AccountService {
    boolean doAccountTransaction(Account source, Account dest, int amount) throws MinimumAmountException;
}

可以看到,在該AccountService接口中定義了一個用于實現賬戶交易的doAccount-Transaction()方法。然后我們提供它的實現類,如代碼清單3-2所示。

代碼清單3-2 AccountService接口實現類代碼

public class AccountServiceImpl implements AccountService {
    private static final Logger LOGGER = Logger.getLogger(AccountServiceImpl.class);

    @Override
    public boolean doAccountTransaction(Account source, Account dest, int amount) throws MinimumAmountException {
        LOGGER.info("執行交易");
        if (amount < 10) {
            throw new MinimumAmountException("交易金額過少");
        }
        return true;
    }
}

在doAccountTransaction()方法中,我們在執行交易之前記錄了操作日志,這種實現方式看上去沒有什么問題。如果針對交易操作,我們希望在該操作之前、之后、執行過程中以及拋出MinimumAmountException異常時都記錄對應的日志,那么實現起來就沒那么容易了。這個時候,可以通過AOP進行切入,并添加對應的日志記錄。基于Spring AOP,其實現過程如代碼清單3-3所示。

代碼清單3-3 AccountServiceAspect代碼

@Aspect
public class AccountServiceAspect {
    private static final Logger LOGGER = Logger.getLogger(AccountServiceAspect.class);

    @Pointcut("execution(* com.springboot.aop.service.AccountService.doAccountTransaction(..))")
    public void doAccountTransaction() {}

    @Before("doAccountTransaction()")
    public void beforeTransaction(JoinPoint joinPoint) {
        LOGGER.info("交易前");
    }

    @After("doAccountTransaction()")
    public void afterTransaction(JoinPoint joinPoint) {
        LOGGER.info("交易后");
    }

    @AfterReturning(pointcut = "doAccountTransaction() and args(source, dest, amount)", returning = "isTransactionSuccessful")
    public void afterTransactionReturns(JoinPoint joinPoint, Account source, Account dest, Double amount, boolean isTransactionSuccessful) {
        if (isTransactionSuccessful) {
            LOGGER.info("轉賬成功 ");
        }
    }

    @AfterThrowing(pointcut = "doAccountTransaction()", throwing = "minimumAmountException")
    public void exceptionFromTransaction(JoinPoint joinPoint, MinimumAmountException minimumAmountException) {
        LOGGER.info("拋出異常: " + minimumAmountException.getMessage());
    }

    @Around("doAccountTransaction()")
    public boolean aroundTransaction(ProceedingJoinPoint proceedingJoinPoint){
        LOGGER.info("調用方法前 ");
        boolean isTransactionSuccessful = false;
        try {
            isTransactionSuccessful = (Boolean)proceedingJoinPoint.proceed();
        } catch (Throwable e) {
        }
        LOGGER.info("調用方法后");
        return isTransactionSuccessful;
    }
}

上述AccountServiceAspect就是一個切面,代表了Spring AOP機制的典型使用方法,我們一一來展開討論。

首先,我們看到這里使用@Pointcut注解定義了一個切點,并通過execution()指示器限定該切點匹配的包結構為com.springboot.aop.service,匹配的方法是AccountService類的doAccountTransaction()方法。也就是說,針對com.springboot.aop.service.AccountService類中doAccountTransaction()方法的任何一次調用,都會觸發切面,也就會執行對應的通知邏輯。請注意,因為在Spring AOP中連接點只支持方法的調用,所以這里專門定義了一個doAccountTransaction()方法,并在該方法上使用了@Pointcut注解。

另外,在AccountServiceAspect中綜合使用了Spring AOP所提供的@Before、@After、@Around、@AfterThrowing和@AfterReturning注解來設置五種不同類型的通知。

  • @Before:在方法調用之前調用通知。
  • @After:在方法完成之后調用通知,無論方法執行成功與否。
  • @Around:通知包裹了目標方法,在被通知的方法調用之前和調用之后執行自定義的行為。
  • @AfterThrowing:在方法拋出異常后進行通知,可以通過該注解指定目標異常信息。
  • @AfterReturning:在方法執行成功之后調用通知。

在使用這些通知注解時,同樣需要注意它們的目標切點都是添加了@Pointcut注解的doAccountTransaction()方法。這些注解對應的實現方法都不復雜,這里不一一展開討論。當執行AccountServiceImpl的doAccountTransaction()方法時,我們在控制臺中能夠看到如代碼清單3-4所示的日志信息,這說明Spring AOP已經生效。

代碼清單3-4 AOP輸出日志代碼示例

INFO  AccountServiceAspect:50 - 調用方法前
INFO  AccountServiceAspect:27 - 交易前
INFO  AccountServiceImpl:14 - 執行交易
INFO  AccountServiceAspect:32 - 交易后
INFO  AccountServiceAspect:58 - 調用方法后

本案例的詳細實現代碼可以在以下地址下載:https://github.com/tianminzheng/spring-boot-examples/tree/main/SpringAopExample

主站蜘蛛池模板: 枝江市| 扎赉特旗| 盐城市| 象州县| 定结县| 闽侯县| 呼和浩特市| 电白县| 开鲁县| 阳谷县| 蒲江县| 康平县| 微博| 屏东县| 和田市| 星子县| 新巴尔虎左旗| 昌乐县| 蕉岭县| 厦门市| 新闻| 南宁市| 大兴区| 台北市| 乐平市| 嘉定区| 麦盖提县| 东明县| 东港市| 苏尼特左旗| 佳木斯市| 汾西县| 渭南市| 陵水| 大城县| 长治县| 长顺县| 墨玉县| 安徽省| 高碑店市| 罗平县|