Spring 切面執(zhí)行鏈的實現(xiàn)示例
在實際應用中,一個方法通常會被多個切面攔截。例如,我們有一個方法,既需要記錄其執(zhí)行日志,又需要應用一些安全限制。這類職責通常由專門的切面來處理,因此在該場景下,會有兩個切面作用于同一個方法的執(zhí)行過程。同時使用多個切面沒有任何問題,但有時切面的執(zhí)行順序非常重要,因為有些切面會控制切入點方法的執(zhí)行,比如鑒權的切面在鑒權失敗后便不會繼續(xù)執(zhí)行切入點方法。這種情況下其他切面可能就沒有機會執(zhí)行了。
// UserService.java
@Service
public class UserService {
private final Logger logger = Logger.getLogger(UserService.class.getName());
@ToLog
public String getUser(String username) throws Exception {
logger.info("getUser method called with username: " + username);
return username;
}
}
// LoggingAspect.java
// 定義日志切面
@Aspect
public class LoggingAspect {
// 定義日志記錄器
private final Logger logger = Logger.getLogger(LoggingAspect.class.getName());
// 定義日志環(huán)繞通知
@Around("@annotation(dev.xyz.annotation.ToLog)")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
// 切入點方法執(zhí)行前執(zhí)行
logger.info("Logging before method: " + joinPoint.getSignature().getName());
// 執(zhí)行切入點方法
Object result = joinPoint.proceed();
// 切入點方法執(zhí)行后執(zhí)行
logger.info("Logging after method: " + joinPoint.getSignature().getName());
// 修改切入點方法的返回值
return result;
}
}
// SecurityAspect.java
// 定義鑒權切面
@Aspect
public class SecurityAspect {
private final Logger logger = Logger.getLogger(SecurityAspect.class.getName());
@Around("@annotation(dev.xyz.annotation.ToLog)")
public Object checkSecurity(ProceedingJoinPoint joinPoint) throws Throwable {
logger.info("Security check performed.");
// 這里模擬鑒權失敗
if (joinPoint.getArgs()[0].equals("Mark")) {
throw new Exception("Security check failed.");
}
Object result = joinPoint.proceed();
logger.info("Security check passed.");
return result;
}
}
// ProjectConfig.java
// Spring 配置,創(chuàng)建兩個切面 bean
@Configuration
@ComponentScan(basePackages = "dev.xyz.service")
@EnableAspectJAutoProxy
public class ProjectConfig {
@Bean
SecurityAspect securityAspect() {
return new SecurityAspect();
}
@Bean
LoggingAspect loggingAspect() {
return new LoggingAspect();
}
}
// Main.java
// 在 main 方法中進行測試
public class Main {
public static void main(String[] args) throws Exception {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProjectConfig.class);
UserService userService = context.getBean(UserService.class);
userService.getUser("Mark");
}
}這里先執(zhí)行了 SecurityAspect 切面,因為鑒權失敗,所以 LoggingAspect 切面不會執(zhí)行。

這種情況下,可以使用 @Order 注解來控制切面執(zhí)行的順序,給注解傳遞一個數(shù)值作為參數(shù),數(shù)值越小越先執(zhí)行,現(xiàn)在給切面類添加上 @Order 注解,讓 LoggingAspect 先于 SecurityAspect 執(zhí)行:
// LoggingAspect.java
// 定義日志切面
@Aspect
@Order(1)
public class LoggingAspect {
// 這里的代碼不變
// ...
}
// SecurityAspect.java
// 定義鑒權切面
@Aspect
public class SecurityAspect {
// 這里的代碼不變
// ...
}現(xiàn)在結果變的不一樣了,先執(zhí)行了 LoggingAspect 切面:

如果存在多個 @Order 數(shù)值一樣的切面,這時的結果又和不使用 @Order 一樣了。不使用 @Order 注解的切面永遠晚于使用 @Order 注解的切面執(zhí)行。
到此這篇關于Spring 切面執(zhí)行鏈的實現(xiàn)示例的文章就介紹到這了,更多相關Spring 切面執(zhí)行鏈內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot 項目如何在tomcat容器中運行的實現(xiàn)方法
這篇文章主要介紹了SpringBoot 項目如何在tomcat容器中運行的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09
SpringBoot整合SpringDataRedis的示例代碼
這篇文章主要介紹了SpringBoot整合SpringDataRedis的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-05-05
解析SpringBoot中@Autowire注解的實現(xiàn)原理
在開發(fā)Java項目時,依賴注入是一種常見的實現(xiàn)方式,SpringBoot框架通過@Autowired注解來實現(xiàn)依賴注入的功能,本文將介紹SpringBoot中 Autowired注解實現(xiàn)的原理2023-06-06
spring boot使用@Async異步注解的實現(xiàn)原理+源碼
通常我們都是采用多線程的方式來實現(xiàn)上述業(yè)務功能,但spring 提供更優(yōu)雅的方式來實現(xiàn)上述功能,就是@Async 異步注解,在方法上添加@Async,spring就會借助AOP,異步執(zhí)行方法,接下來通過本文給大家介紹spring boot異步注解的相關知識,一起看看吧2021-06-06
關于JDK15的新特性之TextBlocks文本塊的引入和使用
這篇文章主要介紹了關于JDK15的新特性之文本塊的引入和使用,如果具有一種語言學機制,可以比多行文字更直觀地表示字符串,而且可以跨越多行,而且不會出現(xiàn)轉義的視覺混亂,那么這將提高廣泛Java類程序的可讀性和可寫性,需要的朋友可以參考下2023-07-07

