Spring Boot 配置 AOP

本文介绍了SpringBoot中如何使用AOP进行动态代码增强,通过创建切面、定义切入点、通知等实现方法执行监控。示例展示了如何配置AOP来监控UserService类的方法,包括前置、后置、返回和异常通知,以及环绕通知的使用,从而在运行时动态添加日志记录。
摘要由CSDN通过智能技术生成

配置 AOP

1. AOP简介

要介绍面向切面编程(Aspect-Oriented Programming,AOP) ,需要首先考虑这样一个场景:公司有一个人力资源管理系统目前已经上线,但是系统运行不稳定,有时运行得很慢,为了检测出到底是哪个环节出问题了,开发人员想要监控每一个方法的执行时间,再根据这些执行时间判断出问题所在。当问题解决后,再把这些监控移除掉。系统目前已经运行,如果手动修改系统中成千上万个方法,那么工作量未免太大,而且这些监控方法以后还要移除掉;如果能够在系统运行过程中动态添加代码,就能很好地解决这个需求。这种在系统运行时动态添加代码的方式称为面向切面编程(AOP)。Spring框架对AOP提供了很好的支持。在AOP中,有一些常见的概念需要读者了解。

  • Joinpoint (连接点):类里面可以被增强的方法即为连接点。例如,想修改哪个方法的功能,那么该方法就是一个连接点。
  • Pointcut(切入点):对Joinpoint进行拦截的定义即为切入点。例如,拦截所有以insert 开始的方法,这个定义即为切入点。
  • Advice (通知):拦截到Joinpoint 之后所要做的事情就是通知。例如,上文说到的打印日志监控。通知分为前置通知、后置通知、异常通知、最终通知和环绕通知。
  • Aspect ( 切面): Pointcut 和Advice的结合。
  • Target (目标对象):要增强的类称为Target。

2. Spring Boot支持

Spring Boot 在Spring 的基础上对AOP的配置提供了自动化配置解决方案spring-boot-starter-aop,使开发者能够更加便捷地在Spring Boot项目中使用AOP。配置步骤如下。

首先在Spring Boot Web项目中引入spring- boot-starter-aop依赖,代码如下:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

然后在org.sang.aop.service包下创建UserService类,代码如下:

@Service
public class UserService {
    public String getUserById(Integer id){
        System.out.println("get...");
        return "user";
    }
    public void deleteUserById(Integer id){
        System.out.println("delete...");
    }
}

接下来创建切面,代码如下:

@Component
@Aspect
public class LogAspect {
    @Pointcut("execution(* com.example.*.*(..))")
    public void pc1() {
    }

    @Before(value = "pc1()")
    public void before(JoinPoint jp) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法开始执行...");
    }

    @After(value = "pc1()")
    public void after(JoinPoint jp) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法执行结束...");
    }

    @AfterReturning(value = "pc1()", returning = "result")
    public void afterReturning(JoinPoint jp, Object result) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法返回值为: " + result);
    }

    @AfterThrowing(value = "pc1 ()", throwing = "e")
    public void afterThrowing(JoinPoint jp, Exception e) {
        String name = jp.getSignature().getName();
        System.out.println(name + "方法抛异常了,异常是: " + e.getMessage());
    }

    @Around("pc1()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        return pjp.proceed();
    }
}

代码解释:

  • @Aspect注解表明这是一个切面类。

  • 第4~6行定义的pcl方法使用了@Pointcut注解,这是一个切入点定义。execution 中的第一个 * 表示方法返回任意值,第二个 * 表示service 包下的任意类,第三个 * 表示类中的任意方法,括号中的两个点表示方法参数任意,即这里描述的切入点为service 包下所有类中的所有方法。

  • 第 8~12行定义的方法使用了@Before注解,表示这是一个前置通知,该方法在目标方法执行之前执行。通过JoinPoint参数可以获取目标方法的方法名、修饰符等信息。

  • 第14~18行定义的方法使用了@After注解,表示这是一个后置通知,该方法在目标方法执行之后执行。

  • 第 20~24行定义的方法使用了@AfterReturning注解,表示这是一个返回通知,在该方法中可以获取目标方法的返回值。@AfterReturmning 注解的returning参数是指返回值的变量名,对应方法的参数。注意,在方法参数中定义了result 的类型为Object,表示目标方法的返回值可以是任意类型,若result 参数的类型为Long,则该方法只能处理目标方法返回值为Long的情况。

  • 第26~30行定义的方法使用了@AfterThrowing注解,表示这是一个异常通知,即当目标方法发生异常时,该方法会被调用,异常类型为Exception 表示所有的异常都会进入该方法中执行,若异常类型为ArithmeticException,则表示只有目标方法抛出的ArithmeticException异常才会进入该方法中处理。

  • 第32~35行定义的方法使用了@Around注解,表示这是一一个环绕通知。环绕通知是所有通知里功能最为强大的通知,可以实现前置通知、后置通知、异常通知以及返回通知的功能。目标方法进入环绕通知后,通过调用ProceedingJoinPoint对象的proceed方法使目标方法继续执行,开发者可以在此修改目标方法的执行参数、返回值等,并且可以在此处理目标方法的异常。

配置完成后,接下来在Controller 中创建接口,分别调用UserService中的两个方法,即可看到LogAspect中的代码动态地嵌入目标方法中执行了。UserController 类的定义如下:

@RestController
public class UserController {
    @Autowired
    UserService userService;

    @GetMapping("/getUserById")
    public String getUserById(Integer id) {
        return userService.getUserById(id);
    }

    @GetMapping("/deleteUserById")
    public void deleteUserById(Integer id) {
        userService.deleteUserById(id);
    }
}

当访问/getUserById 接口时,打印日志,如图所示

getUserById方法开始执行...
get...
getUserById方法返回值为: user
getUserById方法执行结束...
Spring Boot配置AOP,需要遵循以下步骤: 1. 添加AOP依赖 在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` 2. 创建切面类 在切面类中,编写需要执行的切面方法。例如,下面的切面类定义了一个方法,在执行被标注了@LogAnnotation注解的方法前后,打印日志: ```java @Aspect @Component public class LogAspect { private final Logger logger = LoggerFactory.getLogger(LogAspect.class); @Pointcut("@annotation(com.example.demo.annotation.LogAnnotation)") public void logPointCut() { } @Before("logPointCut()") public void before(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); logger.info("Executing method: {}", method.getName()); } @After("logPointCut()") public void after(JoinPoint joinPoint) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); logger.info("Finished executing method: {}", method.getName()); } } ``` 上面的切面类使用@Aspect注解标注,同时也需要被@Component注解标注,以便Spring Boot能够扫描到它。 3. 配置AOP 在应用程序的配置文件(如application.properties)中,可以配置AOP的一些属性,例如开启AspectJ自动代理: ``` spring.aop.auto=true ``` 这样,Spring Boot会自动为标注有@Aspect注解的切面类创建代理对象。 4. 使用AOP 在需要使用AOP的地方,使用@LogAnnotation注解标注即可: ```java @RestController public class HelloController { @GetMapping("/hello") @LogAnnotation public String hello() { return "Hello, World!"; } } ``` 这样,在执行hello()方法前后,就会触发LogAspect中定义的before()和after()方法,打印日志。 总结 通过上面的步骤,就可以在Spring Boot配置AOP了。在实际开发中,我们可以使用AOP来实现日志记录、事务管理、安全检查等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值