前言:AspectJ 不是 Spring框架的組成部分,是獨立的AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用進行 AOP 操作
一.AOP相關術語
比如某個類中有如下4個方法:
Class A{
add();
delete();
update();
select();
}
1.連接點(JoinPoint)
類A中的4個方法都可能被增強,這4個方法成為連接點
2.切入點(PointCut)
如果我實際只增強 add()和update()方法,則add()和update()稱為切入點;
即實際被真正增強方法
3.通知、增強(Advice)
比如我增強add()方法,在add()方法執行之前加上判斷代碼,這個判斷代碼就稱為通知;
即實際增強的邏輯部分稱為通知或增強
通知的五種型別:
- 前置通知 :在執行add()方法之前有一些邏輯部分
- 后置通知(回傳通知):在執行add()方法之后有一些邏輯部分
- 環繞通知:在執行add()方法之前和之后都有一些邏輯部分
- 例外通知:當執行add()方法出現例外時會執行的邏輯部分
- 最終通知:與try-catch-finally中的finally類似,最終一定會執行的邏輯部分
4.切面(Aspect)
切面是一個動作,把我們的通知應用到切入點的程序叫做切面,
比如把判斷代碼加到add()方法之前的這個程序稱為切面,
二.切入點運算式
切入點運算式的作用是知道對哪個類里面的哪個方法進行增強,
1.切入點運算式的格式
execution([權限修飾符][回傳值型別][類全路徑][方法名稱]([引數串列])[例外])
其中回傳值型別、方法名稱和引數串列是必填的,
2.切入點運算式通配符:
- *:匹配所有字符
- …:一般用于匹配多個包,多個引數
- +:表示類及其子類
舉例 1:對 aop.annotation.Student 類里面的 eat方法進行增強 execution(public void aop.annotation.Student.eat(…))
舉例 2:對 aop.annotation.Student 類里面的所有的方法進行增強 execution(* aop.annotation.Student.* (…))
舉例 3:對 aop.annotation 包里面所有類,類里面所有方法進行增強 execution(* aop.annotation.. (…))
3.代碼示例:
StudentProxy類:
@Component
@Aspect
public class StudentProxy {
//前置通知
@Before(value = "execution(public void aop.annotation.Student.eat(..))")
public void beforeDemo(){
System.out.println("餓了!");
}
//后置通知(回傳通知)
@AfterReturning("execution(* aop.annotation.Student.*(..))")
public void afterReturningDemo(){
System.out.println("飯后甜點");
}
//最終通知
@After(value = "execution(void aop.annotation.Student.eat(..))")
public void afterDemo(){
System.out.println("飽了!");
}
//例外通知
@AfterThrowing("execution(void aop.annotation.Student.eat(..))")
public void afterThrowingDemo(){
System.out.println("噎住了!");
}
//環繞通知
@Around("execution(* aop.annotation.Student.*(..))")
public void aroundDemo(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("吃飯前...");
//被增強的方法執行
proceedingJoinPoint.proceed();
System.out.println("吃飯后...");
}
}
Student類:
@Component
public class Student {
public void eat(){
System.out.println("eat something!");
}
}
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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--開啟注解掃描-->
<context:component-scan base-package="aop.annotation"></context:component-scan>
<!--開啟Aspect生成代理物件-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
測驗類:
public class DemoTest {
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("aop/annotation/bean.xml");
Student student = context.getBean("student", Student.class);
student.eat();
}
}
輸出結果:
吃飯前...
餓了!
eat something!
飯后甜點
飽了!
吃飯后...
Process finished with exit code 0
更改Student中代碼,讓其報錯,如下:
@Component
public class Student {
public void eat(){
int i = 1/0;
System.out.println("eat something!");
}
}
輸出結果:

4.相同切入點抽取
pointDemo方法上使用@Pointcut注解,把上述代碼中的前置通知的切入點運算式用pointDemo方法替換;
同理其他的切入點運算式都可以用其替換,方便開發,
//相同切入點抽取
@Pointcut(value = "execution(* aop.annotation.Student.eat(..))")
public void pointDemo(){
}
//前置通知
@Before(value = "pointDemo()")
public void beforeDemo(){
System.out.println("餓了!");
}
5.@Order(數字型別值)注解
當有多個增強類對同一個方法進行增強時,可以使用@Order(數字型別值)注解來進行優先級設定,數字型別值越小,優先級越高,越優先執行,
在創建一個StudentOneProxy類對Student類中對eat方法進行增強,設定@Order(2),StudentOneProxy如下:
@Component
@Aspect
@Order(2)
public class StudentOneProxy {
@Before("execution(* aop.annotation.Student.eat(..))")
public void BeforeDemo(){
System.out.println("StudentOneProxy.BeforeDemo...");
}
@Around("execution(* aop.annotation.Student.eat(..))")
public void aroundDemo(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("StudentOneProxy.Around...");
proceedingJoinPoint.proceed();
System.out.println("StudentOneProxy.Around...");
}
}
在StudentProxy類上添加@Order(1)注解,截圖如下:

輸出結果:
吃飯前...
餓了!
StudentOneProxy.Around...
StudentOneProxy.BeforeDemo...
eat something!
StudentOneProxy.Around...
飯后甜點
飽了!
吃飯后...
Process finished with exit code 0
可以看到設定為@Order(1)的Student類先執行,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/241049.html
標籤:java
上一篇:python模塊——wxpython模塊-改變圖片大小(圖片按鈕)——2020.12.26
下一篇:求助!急!python專案
