概念
??????? 這里需要提前了解什么是Spring的AOP(Aspect Oriented Programming)。是在OOP(面向?qū)ο螅┧枷氲囊环N拓展思想。簡單來說就是將某個代碼塊嵌入到其它的代碼塊中。筆者先前學(xué)Spring也有學(xué)什么IoC啊AOP啊,但實際上沒有用過、就那聽過學(xué)過沒啥用的。。沒會兒就忘記了。那種也就是個了解,好像知道是個什么事兒?當(dāng)時還特地去背關(guān)于AOP的那幾個專有名詞?現(xiàn)在想想有點好笑。
??????? 不過還是需要提前鞏固知道幾個詞??赐炅讼旅娴倪@三個詞的用法就開始進入模擬實戰(zhàn)。
切面(Aspect):由切點和通知組成。即使用@Aspect注解的類
切點(Pointcut):可以限定訪問修飾符、類全限定名、方法名和參數(shù)類型,甚至用于匹配注解
通知(Advice):想要嵌入到其它代碼塊的代碼塊。其中包括五種類型。
????????@Before(目標(biāo)方法執(zhí)行前執(zhí)行)
????????@After(目標(biāo)方法執(zhí)行后執(zhí)行)
????????@AfterReturning(目標(biāo)方法返回結(jié)果后不出現(xiàn)異常才執(zhí)行)
????????@AfterThrowin(出現(xiàn)異常才執(zhí)行)
????????@Around(以上都包括)文章來源:http://www.zghlxwxcb.cn/news/detail-635496.html
引入依賴
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 簡化開發(fā) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
創(chuàng)建注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
/**
* 描述
*
* @return {String}
*/
String value();
}
業(yè)務(wù)代碼
@Slf4j
@RestController
@RequestMapping("/log")
public class LogController {
@Log("AOP測試")
@GetMapping("/aspect")
public void aspect() {
log.info("進入AOP測試方法");
for(int i = 0; i < 10; ++i) {
log.info("執(zhí)行業(yè)務(wù)邏輯{}", i);
}
log.info("結(jié)束AOP測試方法");
}
}
編寫切面
有切點
@Slf4j
@Component
@Aspect
public class LogAspect {
@Autowired
private ApplicationEventPublisher publisher;
/**
* 切點
* 這里面主要掌握兩個東西:
* 1、如果使用注解的話就需要獲取注解的類全限定名
* 2、執(zhí)行的execution表達式(這是比較重要掌握的) 這里面有四個參數(shù) 需要知道的是*也可以表示前綴或者后綴 和SQL中的"%"類似
* 一、方法的訪問權(quán)限修飾符(public/protected/default/private)
* 二、方法的返回值類型
* 三、類的全限定名(包名.類名)
* 四、*(..)的第一個表示方法名;括號內(nèi)表示參數(shù),而兩個點表示接收任何參數(shù)類型
*/
@Pointcut("@annotation(com.chf.annotation.Log) && execution(public * com.chf.controller.*Controller.*(..))")
public void logPointcut() {}
@SneakyThrows
@Around("logPointcut()")
public Object around(ProceedingJoinPoint point) {
// 獲取注解完后解析其內(nèi)部的屬性
MethodSignature signature = (MethodSignature) point.getSignature();
log.info("獲取注解,{}", signature); // void com.chf.controller.LogController.aspect()
Method method = signature.getMethod();
log.info("獲取注解的方法,{}", method);// public void com.chf.controller.LogController.aspect()
Log logAnnotation = method.getAnnotation(Log.class);
log.info("獲取使用注解的value參數(shù),{}", logAnnotation.value()); // AOP測試
// 發(fā)送異步事件
Long startTime = System.currentTimeMillis();
Object o;
try {
o = point.proceed();
} finally {
// 這里可以使用發(fā)布訂閱模式發(fā)布異步事件 至于使用哪一種發(fā)布訂閱模式就看業(yè)務(wù)場景了
Long endTime = System.currentTimeMillis();
publisher.publishEvent(new LogEvent("事件處理的時間是:" + (endTime - startTime) + "ms"));
}
return o;
}
}
無切點
@Slf4j
@Component
@Aspect
public class LogAspect {
@Autowired
private ApplicationEventPublisher publisher;
@SneakyThrows
@Around("@annotation(logAnnotation) && execution(public * com.chf.controller.*Controller.*(..))")
public Object around(ProceedingJoinPoint point, Log logAnnotation) {
// 獲取注解完后解析其內(nèi)部的屬性
MethodSignature signature = (MethodSignature) point.getSignature();
log.info("獲取注解,{}", signature); // void com.chf.controller.LogController.aspect()
Method method = signature.getMethod();
log.info("獲取注解的方法,{}", method);// public void com.chf.controller.LogController.aspect()
Log logAnnotation = method.getAnnotation(Log.class);
log.info("獲取使用注解的value參數(shù),{}", logAnnotation.value()); // AOP測試
// 發(fā)送異步事件
Long startTime = System.currentTimeMillis();
Object o;
try {
o = point.proceed();
} finally {
Long endTime = System.currentTimeMillis();
publisher.publishEvent(new LogEvent("事件處理的時間是:" + (endTime - startTime) + "ms"));
}
return o;
}
}
測試
??????? 不了解Spring的發(fā)布訂閱模式可以看這篇博文:https://blog.csdn.net/m0_65563175/article/details/131899828?spm=1001.2014.3001.5501文章來源地址http://www.zghlxwxcb.cn/news/detail-635496.html
到了這里,關(guān)于【Spring AOP】結(jié)合日志面向切面編程 兩種寫法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!