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()执行后----------------------------
后置环绕通知!!!
************************************************************************************************