SpringBoot之AOP详解
发布日期:2025-05-05 15:50:33 浏览次数:4 分类:精选文章

本文共 5206 字,大约阅读时间需要 17 分钟。

Spring Boot AOP入门指南

1. AOP概述

面向方面编程(AOP)是一种补充面向对象编程(OOP)的编程范式。与OOP中以类为基本单位的模块化思想不同,AOP以切面(Aspect)作为模块化的基本单位。AOP允许我们在不修改源代码的情况下,通过动态代理的方式扩展程序功能。

2. 准备工作

2.1 安装AOP依赖

在项目的build.gradle文件中,添加以下依赖:

compile "org.springframework.boot:spring-boot-starter-aop:${springBootVersion}"

2.2 配置应用程序

在application.yml中添加以下配置:

spring:
aop:
proxy-target-class: true

3. 切入点定义

3.1 定义切点

切点是AOP的核心概念,用于定义需要进行增强的方法或方法调用。切点的定义基于以下规则:

  • 方法的签名(返回类型、方法名、参数类型)
  • 方法的访问权限(public、protected、private)
  • 方法的修饰词(public、protected、private、static、final等)

示例:

@Pointcut("execution(public String test(..))")
public void cutOffPoint() {}

3.2 示例说明

在以下代码中,@Pointcut注解定义了一个切点,表示所有返回类型为String、方法名为test且接受任意参数的方法。例如:

@GetMapping("hello")
public String test() {
logger.info("欢迎关注Java知音");
return "i love java";
}

如果你想在所有返回类型为Area的方法中定义切点,可以使用以下方式:

@Pointcut("execution(public com.example.entity.Area (..))")

4. 通知机制

AOP的核心功能在于通过切点定义的方法,执行特定的通知逻辑。常见的通知类型包括:

4.1 前置通知(@Before)

前置通知在切点开始执行时调用。示例:

@Before("cutOffPoint()")
public void beforeTest() {
logger.info("我在test方法之前执行");
}

4.2 后置通知(@After)

后置通知在切点执行完成后调用。示例:

@After("cutOffPoint()")
public void doAfter() {
logger.info("我是在test之后执行的");
}

4.3 环绕通知(@Around)

环绕通知不仅包括前置和后置通知,还包含目标方法的执行。proceed()方法用于调用目标方法。示例:

@Around("cutOffPoint()")
public Object doAround(ProceedingJoinPoint pjp) {
ThreadLocal
startTime = new ThreadLocal
();
startTime.set(System.currentTimeMillis());
logger.info("我是环绕通知执行");
Object obj;
try {
obj = pjp.proceed();
logger.info("执行返回值 : " + obj);
logger.info(pjp.getSignature().getName() + "方法执行耗时: " + (System.currentTimeMillis() - startTime.get()));
} catch (Throwable throwable) {
obj = throwable.toString();
}
return obj;
}

4.4 返回结果后的通知(@AfterReturning)

@AfterReturning用于在切点执行并返回结果后调用。示例:

@AfterReturning(returning = "result", pointcut = "cutOffPoint()")
public void doAfterReturning(Object result) throws Throwable {
logger.info("大家好,我是@AfterReturning,他们都秀完了,该我上场了");
}

4.5 错误处理后的通知(@AfterThrowing)

@AfterThrowing用于在切点抛出异常后调用。示例:

@AfterThrowing(throwing = "e", pointcut = "cutOffPoint()")
public void doAfterThrowing(Throwable e) {
logger.info("大家好,我是@AfterThrowing,他们犯的错误,我来背锅");
logger.info("错误信息" + e.getMessage());
}

5. AOP的实际应用场景

5.1 全局异常处理

通过定义切点拦截ResultBeanPageResultBean的方法调用,实现全局异常处理。示例:

@Pointcut(value = "execution(public com.example.beans.PageResultBean *(..))")
public void handlerPageResultBeanMethod() {}
@Pointcut(value = "execution(public com.example.beans.ResultBean *(..))")
public void handlerResultBeanMethod() {}
@Around("handlerPageResultBeanMethod()")
public Object handlerPageResultBeanMethod(ProceedingJoinPoint pjp) {
ThreadLocal
start = new ThreadLocal
();
start.set(System.currentTimeMillis());
try {
PageResultBean resultBean = new PageResultBean();
resultBean.setMsg("处理成功");
resultBean.setCode(ResultBean.SUCCESS);
PageResultBeanThreadLocal.set(resultBean);
logger.info(pjp.getSignature() + "方法执行耗时: " + (System.currentTimeMillis() - start.get()));
} catch (Throwable e) {
logger.error(pjp.getSignature() + "错误处理", e);
ResultBean resultBean = new ResultBean();
resultBean.setMsg("处理失败");
resultBean.setCode(ResultBean.FAIL);
PageResultBeanThreadLocal.set(resultBean);
}
return PageResultBeanThreadLocal.get();
}

5.2 事物管理

默认情况下,Spring Boot的AOP不支持事物管理。如果需要实现事物管理,需要在切点中调用@Transactional注解。例如:

@Transactional
public int insertSelective(Area record) {
record.setAddress("test");
record.setPostalcode(88888);
record.setType(3);
int i = areaMapper.insertSelective(record);
return i;
}

如果需要实现回滚,可以在catch中抛出异常。

6. 日志处理配置

6.1 禁用Spring Boot自带日志

在build.gradle中添加:

configurations {
providedRuntime
all*.exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
ext {
springBootVersion = '2.0.1.RELEASE'
}
dependencies {
compile "org.springframework.boot:spring-boot-starter-log4j2:${springBootVersion}"
}

6.2 配置log4j2日志

在application.yml中添加:

logging:
level:
com:
example:
dao: debug
config: classpath:log4j2-spring.xml

6.3 log4j2配置文件

6.4 使用日志

在需要打印日志的类中添加:

private static final Logger logger = LoggerFactory.getLogger(YourClass.class);
public static void main(String[] args) {
logger.error("error级别日志");
logger.warn("warning级别日志");
logger.info("info级别日志");
}

通过合理使用日志,开发人员可以在开发环境中打印详细信息,而在线环境中可以将日志级别设置为warningerror,以减少不必要的日志输出。

7. 常见问题解答

7.1 事物回滚问题

如果在业务方法中使用@Transactional注解,并且在catch中不抛出异常,事物管理器将不会回滚事务。要实现回滚,可以在catch中抛出一个异常。

7.2 全局异常处理

通过AOP切入拦截ResultBeanPageResultBean的方法调用,可以实现全局异常处理,避免在业务层逐一处理错误。

8. 总结

AOP是一种强大的编程范式,能够在不修改源代码的情况下扩展程序功能。通过合理使用切点和通知机制,可以实现全局异常处理、日志记录、性能监控等功能。在实际应用中,建议结合事物管理和日志处理,提升程序的健壮性和可维护性。

上一篇:PLC结构体(西门子)
下一篇:Quarzt定时调度任务

发表评论

最新留言

关注你微信了!
[***.104.42.241]2026年05月28日 05时08分38秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章