https://blog.csdn.net/qq_40794973/article/details/90313894
pom.xml
<!--spring 的任何部分的運(yùn)行都需要ioc的支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
<!--AOP解析切入點(diǎn)表達(dá)式-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
賬戶的業(yè)務(wù)層接口
package com.itheima.service;
/**
* 賬戶的業(yè)務(wù)層接口
* 下面有三個(gè)不同類型的方法
*/
public interface IAccountService {
/**
* 模擬保存賬戶
*/
void saveAccount();
}
賬戶的業(yè)務(wù)層接口實(shí)現(xiàn)
package com.itheima.service.impl;
import com.itheima.service.IAccountService;
import org.springframework.stereotype.Service;
/**
* 賬戶的業(yè)務(wù)層實(shí)現(xiàn)類
*/
@Service("accountService")
public class AccountServiceImpl implements IAccountService{
@Override
public void saveAccount() {
System.out.println("執(zhí)行了保存");
}
}
用于記錄日志的工具類兄渺,它里面提供了公共的代碼
package com.itheima.utils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/**
* 公共代碼類
* 用于記錄日志的工具類淌友,它里面提供了公共的代碼
*/
@Component("logger")
@Aspect//表示當(dāng)前類是一個(gè)切面類
public class Logger {
@Pointcut("execution(* com.itheima.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方法開始記錄日志了又兵。任柜。。");
}
/**
* 環(huán)繞通知
* 問題:
* 當(dāng)我們配置了環(huán)繞通知之后沛厨,切入點(diǎn)方法沒有執(zhí)行宙地,而通知方法執(zhí)行了。
* 分析:
* 通過對(duì)比動(dòng)態(tài)代理中的環(huán)繞通知代碼逆皮,發(fā)現(xiàn)動(dòng)態(tài)代理的環(huán)繞通知有明確的切入點(diǎn)方法調(diào)用宅粥,而我們的代碼中沒有。
* 解決:
* Spring框架為我們提供了一個(gè)接口:ProceedingJoinPoint电谣。該接口有一個(gè)方法proceed()秽梅,此方法就相當(dāng)于明確調(diào)用切入點(diǎn)方法。
* 該接口可以作為環(huán)繞通知的方法參數(shù)剿牺,在程序執(zhí)行時(shí)企垦,spring框架會(huì)為我們提供該接口的實(shí)現(xiàn)類供我們使用。
*
* spring中的環(huán)繞通知:
* 它是spring框架為我們提供的一種可以在代碼中手動(dòng)控制增強(qiáng)方法何時(shí)執(zhí)行的方式晒来。
*/
//@Around("pt1()")
public Object aroundPringLog(ProceedingJoinPoint pjp){
Object rtValue = null;
try{
Object[] args = pjp.getArgs();//得到方法執(zhí)行所需的參數(shù)
System.out.println("Logger類中的aroundPringLog方法開始記錄日志了钞诡。。。前置");
rtValue = pjp.proceed(args);//明確調(diào)用業(yè)務(wù)層方法(切入點(diǎn)方法)
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方法開始記錄日志了拗窃。瞎领。。最終");
}
}
}
測試
import com.itheima.service.IAccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
/**
* 測試AOP的配置
*/
@Test
public void testAOP() {
//1.獲取容器
ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext1.xml");
//2.獲取對(duì)象
IAccountService as = (IAccountService) ac.getBean("accountService");
//3.執(zhí)行方法
as.saveAccount();
}
}