淺談@Aspect@Order各個通知的執(zhí)行順序
@Aspect@Order各個通知的執(zhí)行順序
兩個切面類:【記錄日志】和【判斷參數(shù)】,分別對應(yīng)順序 @Order(0) 和@Order(1) 。
本文只是將重點說下 執(zhí)行順序 這么回事哈哈哈
代碼
【業(yè)務(wù)類】
/**
* 登錄控制器
*/
@Controller
public class LoginController {
//向外面拋出異常
public void loginWithThrow(String username, String password) throws Exception {
if (username == null || password == null) {
throw new Exception("登錄信息不可為空啊");
}
System.out.println("LoginController#login...");
}
//拋出異常自己捕獲的情況
public void loginWithTryCatch(String username, String password) {
try{
if (username == null || password == null) {
throw new Exception("登錄信息不可為空啊");
}
System.out.println("LoginController#login...");
}catch (Exception e){
e.printStackTrace();
}
}
}
【切面類】
/**
* 輸出日志注解
*/
@Order(0)
@Aspect
@Component
public class LogAspect {
//抽出共通的execution用的
//com.yuki.demo.aop.aspect 包或者子包下所有類的方法
@Pointcut("execution(* com.yuki.demo.aop.aspect..*.*(..))")
public void pointcut(){
}
//前置通知
// @Before("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
@Before("pointcut()")
public void before() {
System.out.println("LogAspect#before...");
}
//環(huán)繞通知
//ProceedingJoinPoint 只有環(huán)繞通知有
@Around("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("LogAspectA#around開始...");
//代理方法的執(zhí)行,如果沒有joinPoint.proceed() ,則前置通知@Before 不會執(zhí)行,其它的通知正常
joinPoint.proceed();
//執(zhí)行方法之后,如果joinPoint.proceed() 拋出了異常,則該句不會執(zhí)行,拋出異常后直接跳出了aroud方法了
System.out.println("LogAspectA#around結(jié)束...");
}
//后置通知(只要連接點被執(zhí)行,不管是否拋出異常)
@After("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void after() {
System.out.println("LogAspect#after...");
}
//異常通知(只有在joinPoint.proceed()方法執(zhí)行向外面拋出了異常,才會執(zhí)行該通知)
@AfterThrowing("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void afterThrowing() {
System.out.println("LogAspect#afterThrowing...");
}
//正常的返回通知通知(正常結(jié)束了才會執(zhí)行該通知)
@AfterReturning("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void afterReturning() {
System.out.println("LogAspect#afterReturning...");
}
}
【切面類】
/**
* 判斷請求參數(shù)的sign是否正確的 切面類
*/
@Order(1)
@Aspect
@Component
public class SignAspect {
@Around("execution(public void com.yuki.demo.aop.aspect.LoginController.*(String,String))")
public void around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("SignAspect#around開始...");
joinPoint.proceed();
System.out.println("SignAspect#around結(jié)束...");
}
}
【啟動配置】
省略。。。非重點
【測試類】
@SpringBootTest
class AopApplicationTests {
@Autowired
private LoginController loginController;
@Test
void contextLoads() {
loginController.loginWithTryCatch("yuki", "1234");
}
}
【控制臺輸出】
LogAspectA#around開始...
LogAspect#before...
SignAspect#around開始...
LoginController#login...
SignAspect#around結(jié)束...
LogAspectA#around結(jié)束...
LogAspect#after...
LogAspect#afterReturning...
小結(jié)


spring AspectJ order(順序)
@Aspect
@Order(2)
public class HelloWorldAspectAnnotation {
/**
* JoinPoint接口
* @param joinPoint
*/
/*public interface JoinPoint {
String toString(); //連接點所在位置的相關(guān)信息
String toShortString(); //連接點所在位置的簡短相關(guān)信息
String toLongString(); //連接點所在位置的全部相關(guān)信息
Object getThis(); //返回AOP代理對象
Object getTarget(); //返回目標(biāo)對象
Object[] getArgs(); //返回被通知方法參數(shù)列表
Signature getSignature(); //返回當(dāng)前連接點簽名
SourceLocation getSourceLocation();//返回連接點方法所在類文件中的位置
String getKind(); //連接點類型
StaticPart getStaticPart(); //返回連接點靜態(tài)部分
}*/
//定義前置通知,注意這里是sayHello2
//使用@Before進行前置通知聲明,其中value用于定義切入點表達式或引用命名切入點
@Before(value="execution(* com.boventech..*.sayHello2(..))&& args(param)",argNames="param")
public void beforeAdvice(JoinPoint joinPoint,String param) {
System.out.println(1);
System.out.println("=======================");
System.out.println("===param:" + param);
System.out.println("=======================");
System.out.println(joinPoint.getArgs().length);
System.out.println("=======================");
System.out.println(joinPoint.toString());
System.out.println("=======================");
System.out.println(joinPoint.getTarget());
System.out.println("=======================");
System.out.println(joinPoint.getThis());
System.out.println("=======================");
System.out.println("===========before advice");
}
/*value:指定切入點表達式或命名切入點;
pointcut:同樣是指定切入點表達式或命名切入點,如果指定了將覆蓋value屬性指定的,pointcut具有高優(yōu)先級;*/
@AfterReturning(value="execution(* com.boventech..*.sayHello2(..))&& args(param)",argNames="param",pointcut="execution(* com.boventech..*.sayHello2(..))&& args(param)")
public void afterFinallyAdvice(JoinPoint joinPoint,String param) {
System.out.println("param:"+param);
System.out.println("===========");
System.out.println("===========after finally advice");
}
}@Aspect
@Order(1)
public class HelloWorldAspectAnnotation2 {
/**
* JoinPoint接口
* @param joinPoint
*/
/*public interface JoinPoint {
String toString(); //連接點所在位置的相關(guān)信息
String toShortString(); //連接點所在位置的簡短相關(guān)信息
String toLongString(); //連接點所在位置的全部相關(guān)信息
Object getThis(); //返回AOP代理對象
Object getTarget(); //返回目標(biāo)對象
Object[] getArgs(); //返回被通知方法參數(shù)列表
Signature getSignature(); //返回當(dāng)前連接點簽名
SourceLocation getSourceLocation();//返回連接點方法所在類文件中的位置
String getKind(); //連接點類型
StaticPart getStaticPart(); //返回連接點靜態(tài)部分
}*/
//定義前置通知,注意這里是sayHello2
//使用@Before進行前置通知聲明,其中value用于定義切入點表達式或引用命名切入點
@Before(value="execution(* com.boventech..*.sayHello2(..))&& args(param)",argNames="param")
public void beforeAdvice(JoinPoint joinPoint,String param) {
System.out.println(2);
System.out.println("=======================");
}
/*value:指定切入點表達式或命名切入點;
pointcut:同樣是指定切入點表達式或命名切入點,如果指定了將覆蓋value屬性指定的,pointcut具有高優(yōu)先級;*/
@AfterReturning(value="execution(* com.boventech..*.sayHello2(..))&& args(param)",argNames="param",pointcut="execution(* com.boventech..*.sayHello2(..))&& args(param)")
public void afterFinallyAdvice(JoinPoint joinPoint,String param) {
System.out.println("order:" + 2);
}
}public class AopAnnotationTest {
@Test
public void testHelloworld() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("/helloWorld2.xml");
IHelloWorld2Service helloworldService =ctx.getBean("helloWorld2Service", IHelloWorld2Service.class);
String param = "12";
helloworldService.sayHello2(param);
}
}<aop:aspectj-autoproxy/>
<bean id="helloWorld2Service" class="com.boventech.learning.serviceImpl.HelloWorld2ServiceImpl"/>
<bean id="aspect"
class="com.boventech.learning.aspect.HelloWorldAspectAnnotation"/>
<bean id="aspect2"
class="com.boventech.learning.aspect.HelloWorldAspectAnnotation2"/>以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot3整合Mybatis-plus3.5.3報錯問題解決
在日常學(xué)習(xí)springboot3相關(guān)的代碼時,在使用 SpringBoot3 整合 MyBatisplus 時出現(xiàn)了一些問題,花了不少時間處理,這篇文章主要介紹了Springboot3整合Mybatis-plus3.5.3報錯問題解決,需要的朋友可以參考下2023-11-11
JSON.toJSONString()空字段不忽略修改的問題
這篇文章主要介紹了JSON.toJSONString()空字段不忽略修改的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
Mybatis?Mapper中多參數(shù)方法不使用@param注解報錯的解決
這篇文章主要介紹了Mybatis?Mapper中多參數(shù)方法不使用@param注解報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。2022-01-01
JavaWeb中轉(zhuǎn)發(fā)與重定向的區(qū)別小結(jié)
轉(zhuǎn)發(fā)和重定向是JavaWeb中常用的兩種頁面跳轉(zhuǎn)方式,它們在實現(xiàn)上有一些區(qū)別,本文主要介紹了JavaWeb中轉(zhuǎn)發(fā)與重定向的區(qū)別小結(jié),具有一定的參考價值,感興趣的可以了解一下2023-10-10
Java 實戰(zhàn)項目之精美物流管理系統(tǒng)的實現(xiàn)流程
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SpringBoot+Vue+maven+Mysql實現(xiàn)一個精美的物流管理系統(tǒng),大家可以在過程中查缺補漏,提升水平2021-11-11
SpringBoot工程中Spring Security應(yīng)用實踐記錄流程分析
Spring Security是一個能夠為基于Spring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架。這篇文章主要介紹了SpringBoot工程中Spring Security應(yīng)用實踐,需要的朋友可以參考下2021-09-09

