0
点赞
收藏
分享

微信扫一扫

SpringBoot: AOP的基本用法

yundejia 2022-07-27 阅读 101


一、基本使用背景:需要对一批方法进行增强处理的情形。比如,某个service中有100个方法用来给controller层进行调用。现在的需求要给这100个方法上增加如下功能:
1)记录方法被调用的时间和参数
2)记录方法调用的返回时间和返回值
如果按照传统的做法,可能要对这100个方法分别进行修改,这种做法显然是不合理的。而使用AOP(Aspect Oriented Programming),则可以容易实现。
二、Spring Boot AOP的基本用法:
1.在项目的pom.xml中增加相关的依赖( spring-boot-starter-aop 和aspectj ),完整pom如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cn.edu.tju</groupId>
<artifactId>springaop</artifactId>
<version>1.0.0</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
</parent>
<!-- Additional lines to be added here... -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.6</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
</configuration>

</plugin>
</plugins>
</build>


</project>

2.在启动类添加@EnableAspectJAutoProxy注解(如果在application.properties中未显式配置spring.aop.auto=false的话,@EnableAspectJAutoProxy注解也可以省略)

package cn.edu.tju;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class Start {
public static void main(String[] args) {
SpringApplication.run(Start.class,args);
}
}

3.创建service类:

package cn.edu.tju.service;

import org.springframework.stereotype.Service;

@Service
public class InfoService {
public String getHelloInfo(String str){
return "hello,"+str;
}
public String getHiInfo(String str){
return "hi,"+str;
}
}

4.创建controller类,并注入上述InfoService

package cn.edu.tju.controller;

import cn.edu.tju.service.InfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
@Autowired
private InfoService infoService;



@RequestMapping("/hello/{name}")
public String getHello(@PathVariable("name")String name){
//System.out.println(infoService.getClass());
String result=infoService.getHelloInfo(name);
return result;
}

@RequestMapping("/hi/{name}")
public String getHi(@PathVariable("name")String name){
//System.out.println(infoService.getClass());
String result=infoService.getHiInfo(name);
return result;
}
}

5.创建AOP类,用来对service类中被调用的方法进行增强处理:

package cn.edu.tju.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
@Aspect
public class MyAspect {
//execution里的写法表示cn.edu.tju.service包下所有类的所有方法都将被增强处理
//方法调用之前会调用这里定义的这个方法
@Before("execution(* cn.edu.tju.service.*.*(..))")
public void logCallingTime(JoinPoint joinPoint){
System.out.print(new Date().toLocaleString()+" "+joinPoint.getSignature()+" 被调用,参数为: ");
Object[] argList=joinPoint.getArgs();
for(Object object: argList){
System.out.print(object);
System.out.print(" ");

}
System.out.println();
}

//execution里的写法表示cn.edu.tju.service包下所有类的所有方法都将被增强处理
//方法返回时会调用这里定义的这个方法
@AfterReturning(returning = "returnValue",pointcut="execution(* cn.edu.tju.service.*.*(..))")
public void logReturningInfo(JoinPoint joinPoint,Object returnValue){
System.out.println(new Date().toLocaleString()+" " +joinPoint.getSignature()+" 返回 "+returnValue);
}
}

6.运行程序,分别访问:

http://localhost:8093/hi/amadeus
http://localhost:8093/hello/amadeus

可以看到控制台的输出

SpringBoot: AOP的基本用法_spring boot


7.spring boot AOP,默认使用cglib动态代理来实现,无论被代理的类是否实现了某个接口。如果需要让实现了某个接口的被代理类使用jdk动态代理,则需要在application.properties中配置

spring.aop.proxy-target-class=false


举报

相关推荐

0 条评论