1. 程式人生 > 其它 >spring基於 註解的 AOP 的前後置通知,異常通知,最終通知,環繞通知

spring基於 註解的 AOP 的前後置通知,異常通知,最終通知,環繞通知

技術標籤:Spring

1.IAccountService介面和實現類

package com.service;

/**
 * 賬戶業務層的介面
 */
public interface IAccountService {
    public void saveAccount() ;

}

package com.service.impl;

import com.service.IAccountService;
import org.springframework.stereotype.Service;

/**
 * 賬戶的業務層實現類
 */
@Service("accountService"
) public class AccountServiceImpl implements IAccountService{ public void saveAccount() { System.out.println("執行了儲存"); // int i=1/0; } }

2.Logger類

package com.utils;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.
stereotype.Component; @Component("logger") @Aspect//表示當前類是一個切面類 public class Logger { @Pointcut("execution(* com.service.impl.*.*(..))") private void pt1(){} /** * 前置通知 */ @Before("pt1()") public void beforePrintLog(){ System.out.println
("前置通知Logger類中的beforePrintLog方法開始記錄日誌了。。。"); } /** * 後置通知 */ @AfterReturning("pt1()") public void afterReturningPrintLog(){ System.out.println("後置通知Logger類中的afterReturningPrintLog方法開始記錄日誌了。。。"); } /** * 異常通知 */ @AfterThrowing("pt1()") public void afterThrowingPrintLog(){ System.out.println("異常通知Logger類中的afterThrowingPrintLog方法開始記錄日誌了。。。"); } /** * 最終通知 */ @After("pt1()") public void afterPrintLog(){ System.out.println("最終通知Logger類中的afterPrintLog方法開始記錄日誌了。。。"); } /** * 環繞通知 */ // @Around("pt1()") public Object aroundPringLog(ProceedingJoinPoint pjp){ Object rtValue = null; try{ Object[] args = pjp.getArgs();//得到方法執行所需的引數 System.out.println("Logger類中的aroundPringLog方法開始記錄日誌了。。。前置"); rtValue = pjp.proceed(args);//明確呼叫業務層方法(切入點方法) System.out.println("Logger類中的aroundPringLog方法開始記錄日誌了。。。後置"); return rtValue; }catch (Throwable t){ System.out.println("Logger類中的aroundPringLog方法開始記錄日誌了。。。異常"); throw new RuntimeException(t); }finally { System.out.println("Logger類中的aroundPringLog方法開始記錄日誌了。。。最終"); } } }

3.bean.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">

    <!-- 配置spring建立容器時要掃描的包-->
    <context:component-scan base-package="com"></context:component-scan>

    <!-- 配置spring開啟註解AOP的支援 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

4測試

import com.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AOPTest {
    public static void main(String[] args) {
        //1.獲取容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.獲取物件
        IAccountService as = (IAccountService)ac.getBean("accountService");
        //3.執行方法
        as.saveAccount();
    }
}

5結果

在這裡插入圖片描述

6.順序問題

發現這裡最終放在了後置的前面,這個是spring的bug,想要解決只能寫環繞通知

7.基本註解

@Aspect//表明當前類是一個切面類
切入點表示式
@Pointcut(“execution(* com.service.impl..(…))”)
private void pt1(){}
@Before(“pt1()”) 前置通知
@AfterReturning(“pt1()”)後置通知
@AfterThrowing(“pt1()”)異常通知
@After(“pt1()”)最終通知
@Around(“pt1()”)環繞通知