SpringBoot面向切面程式設計(AOP)
阿新 • • 發佈:2020-12-07
Aspect
(與SpringBoot整合)
總結
-
作用位置
try{ try{ @Around 前置環繞通知 @Before 前置通知 method.invoke(..); }catch(){ @AfterThrowing 異常通知 throw.....; }finally{ @After 後置通知 } @AfterReturning 返回通知 }finally{ @Around 後置環繞通知 }
-
執行流程
- 正常情況: @Around ==> @Before ==> 目標方法 ==> @After ==> @AfterReturning ==> @Around;
- 異常情況: @Around ==> @Before ==> 目標方法(出現異常) ==> @AfterThrowing ==> @After ==> @Around;
程式碼演示
1. 引入aop依賴
pom.xml
<!-- 引入AOP依賴 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2. 核心業務類
Service層
UserService.java
@Service public class UserService { public void service1(){ System.out.println("Service-1-執行"); } public String service2(){ System.out.println("Service-2-執行"); //int i = 1/0; //異常測試 return "Success!!!"; } public ArrayList<String> service3(String userName){ System.out.println("Service-3-執行"); ArrayList<String> list = new ArrayList<>(); list.add("Service-3-執行成功!!!"); list.add(userName); return list; } }
3. 切面
MyAspect.java
注:一定要將切面作為Spring元件注入容器
@Component
@Aspect
public class MyAspect {
//定義切入點
@Pointcut("within(com.juyss.service.*)")
public void pointcut(){}
//環繞通知 ===> 正常情況執行在@Before和@After之前,如果執行過程中拋異常,只執行前置環繞通知,後置環繞不執行
@Around(value = "pointcut()")
public Object around(ProceedingJoinPoint point){
System.out.println("前置環繞通知!!!");
Object proceed = null;
try {
System.out.println("point.proceed()執行前----------------------------");
Signature signature = point.getSignature();
System.out.println("獲取類名:"+signature.getName());
System.out.println("point.proceed()執行前----------------------------");
proceed = point.proceed();
System.out.println("point.proceed()執行後----------------------------");
System.out.println("獲取返回值:"+proceed);
System.out.println("point.proceed()執行後----------------------------");
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("後置環繞通知!!!");
return proceed;
}
//前置通知 ===> 方法執行前
@Before("pointcut()")
public void before(){
System.out.println("前置通知生效!!!");
}
//返回通知 ===> 方法正常執行完後執行,可以獲取返回值.如果方法執行過程中拋異常,則不會執行
@AfterReturning(value = "pointcut()",returning = "returnValue")
public void afterReturning(Object returnValue){
System.out.println("返回通知生效!!! ------返回值:"+returnValue);
}
//後置通知 ===> 在finally程式碼塊中執行,無論如何都會執行的通知
@After("pointcut()")
public void after(JoinPoint joinPoint){
Signature signature = joinPoint.getSignature();
System.out.println("後置通知生效!!! ------ 方法名:"+signature.getName());
}
//異常通知 ===> 在執行過程中丟擲異常時執行
@AfterThrowing(value = "pointcut()",throwing = "e")
public void afterThrowing(Exception e){
System.out.println("異常通知生效!!! 異常資訊:"+e.getMessage());
}
}
4. 測試類
AspectApplicationTests.java
@SpringBootTest
class AspectApplicationTests {
@Autowired
private UserService service;
@Test
public void Test(){
service.service1();
System.out.println("************************************************************************");
service.service2();
System.out.println("************************************************************************");
service.service3("方法引數");
System.out.println("************************************************************************");
}
}
5. 測試結果
正常執行時:
前置環繞通知!!!
point.proceed()執行前----------------------------
獲取類名:service1
point.proceed()執行前----------------------------
前置通知生效!!!
Service-1-執行
返回通知生效!!! ------返回值:null
後置通知生效!!! ------ 方法名:service1
point.proceed()執行後----------------------------
獲取返回值:null
point.proceed()執行後----------------------------
後置環繞通知!!!
************************************************************************************************
前置環繞通知!!!
point.proceed()執行前----------------------------
獲取類名:service2
point.proceed()執行前----------------------------
前置通知生效!!!
Service-2-執行
返回通知生效!!! ------返回值:Success!!!
後置通知生效!!! ------ 方法名:service2
point.proceed()執行後----------------------------
獲取返回值:Success!!!
point.proceed()執行後----------------------------
後置環繞通知!!!
************************************************************************************************
前置環繞通知!!!
point.proceed()執行前----------------------------
獲取類名:service3
point.proceed()執行前----------------------------
前置通知生效!!!
Service-3-執行
返回通知生效!!! ------返回值:[Service-3-執行成功!!!, 方法引數]
後置通知生效!!! ------ 方法名:service3
point.proceed()執行後----------------------------
獲取返回值:[Service-3-執行成功!!!, 方法引數]
point.proceed()執行後----------------------------
後置環繞通知!!!
************************************************************************************************
方法執行丟擲異常時
前置環繞通知!!!
point.proceed()執行前----------------------------
獲取類名:service1
point.proceed()執行前----------------------------
前置通知生效!!!
Service-1-執行
返回通知生效!!! ------返回值:null
後置通知生效!!! ------ 方法名:service1
point.proceed()執行後----------------------------
獲取返回值:null
point.proceed()執行後----------------------------
後置環繞通知!!!
************************************************************************************************
前置環繞通知!!!
point.proceed()執行前----------------------------
獲取類名:service2
point.proceed()執行前----------------------------
前置通知生效!!!
Service-2-執行
異常通知生效!!! 異常資訊:/ by zero
後置通知生效!!! ------ 方法名:service2
java.lang.ArithmeticException: / by zero
at com.juyss.service.UserService.service2(UserService.java:25)
##############其他異常資訊省略################
後置環繞通知!!!
************************************************************************************************
前置環繞通知!!!
point.proceed()執行前----------------------------
獲取類名:service3
point.proceed()執行前----------------------------
前置通知生效!!!
Service-3-執行
返回通知生效!!! ------返回值:[Service-3-執行成功!!!, 方法引數]
後置通知生效!!! ------ 方法名:service3
point.proceed()執行後----------------------------
獲取返回值:[Service-3-執行成功!!!, 方法引數]
point.proceed()執行後----------------------------
後置環繞通知!!!
************************************************************************************************