SpringBoot应用AOP及各注解的执行顺序
首先第一步,POM引入jar
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.5.3</version>
</dependency>
第二步随便写一个类,然后类中写一个方法,我这里是写了一个除法运算:
public class MathCalculator {
public int div (int i, int j) {
System.out.println("MathCalculator.div...");
return i / j;
}
}
第三步写一个切面类:
//该注解表示声明该类为一个切面类
@Aspect
public class LogAspects {
//定义一个切点,表达式可以灵活运用,我这个表达式是表示MathCalculator类中所有的方法都进行切入
@Pointcut("execution(public int com.example.demo.aop.MathCalculator.*(..))")
public void pointCut () {}
//方法执行开始之前
@Before("pointCut()")
public void logStart (JoinPoint joinPoint) {
System.out.println("除法运行...参数:{"+ Arrays.asList(joinPoint.getArgs())+"}");
}
//方法执行开始之后
@After("pointCut()")
public void logEnd (JoinPoint joinPoint) {
System.out.println("除法结束..." + joinPoint.getSignature().getName());
}
//当方法进行返回的时候,returning属性是指定方法参数中的result来接收返回参数,这样就可以修改返回参数
@AfterReturning(value = "pointCut()", returning = "result")
public void logReturn (JoinPoint joinPoint, Object result) {
System.out.println("除法正常返回... 返回结果:{"+result+"}");
}
//当方法执行异常的时候,throwding是指定方法参数中的e来接收异常参数,可以查看发生的什么异常
@AfterThrowing(value = "pointCut()", throwing = "e")
public void logException (JoinPoint joinPoint, Exception e) {
System.out.println("异常... 异常信息:{"+e+"}");
}
//环绕通知
@Around("pointCut()")
public Object logAround (ProceedingJoinPoint joinPoint) throws Throwable {
//原方法执行之前会打印这个日志
System.out.println("环绕通知... 开始");
//执行原方法
Object obj = joinPoint.proceed();
//原方法执行结束,打印这行日志
System.out.println("环绕通知... 结束");
//返回方法返回参数
return obj;
}
}
这里要注意一下AOP注解执行的先后顺序
环绕通知... 开始
除法运行...参数:{[1, 1]}
MathCalculator.div...
环绕通知... 结束
除法结束...div
除法正常返回... 返回结果:{1}
运行的顺序是
1、@Around
2、@Before
3、原方法
4、@Around
5、@After
6、@AfterReturning
第四步,写一个配置类,记得一定要加@EnableAspectJAutoProxy注解
//该配置类是为了将我们前2个类(切面类、被切面类)加入到Spring容器中
@Configuration
//启动AOP(一定要加这个注解,切记!!!)
@EnableAspectJAutoProxy
public class SpringOfAOPConfig {
@Bean
public MathCalculator mathCalculator () {
return new MathCalculator();
}
@Bean
public LogAspects logAspects () {
return new LogAspects();
}
}
第五步,测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Test
public void contextLoads() {
//根据配置类获取SPring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringOfAOPConfig.class);
//从容器中获取Bean
MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
//执行除法运算
mathCalculator.div(1, 1);
//关闭容器
applicationContext.close();
}
}
正常结果:
2018-12-11 11:01:25.496 INFO 16364 --- [ main] com.example.demo.DemoApplicationTests : Started DemoApplicationTests in 3.455 seconds (JVM running for 4.972)
环绕通知... 开始
除法运行...参数:{[1, 1]}
MathCalculator.div...
环绕通知... 结束
除法结束...div
除法正常返回... 返回结果:{1}
2018-12-11 11:01:25.807 INFO 16364 --- [ Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
异常结果:
2018-12-11 11:11:22.205 INFO 9628 --- [ main] com.example.demo.DemoApplicationTests : Started DemoApplicationTests in 3.532 seconds (JVM running for 4.559)
环绕通知... 开始
除法运行...参数:{[1, 0]}
MathCalculator.div...
除法结束...div
异常... 异常信息:{java.lang.ArithmeticException: / by zero}
java.lang.ArithmeticException: / by zero
看到没:
当发生异常的时候@Around的方法执行后切入没有进行,但是@After的方法却执行了,所以原方法发生异常后顺序就是
1、@Around
2、@Brfore
3、原方法
4、@After
5、@AfterThrowing
标签:
java
, spring boot
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)