如果饿了就吃,困了就睡,渴了就喝,人生就太无趣了
源码地址:https://github.com/keer123456789/springbootstudy/tree/master/aopdemo
1.依赖引入
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
2.创建切面
创建切面类AspectLog
,该类作用是在方法前后打印日志。代码如下:
@Component
注解将切面类声明为bean,注入到spring容器中。@Aspect
注解将类声明为切面类@Pointcut
定义切点(用于准确定位应该在什么地方应用切面通知),execution
用来定位切点,使用方法如图1:可以是使用通配符*
匹配任意字符。@Before
在方法前执行@After
在方法后执行@AfterReturning
在方法执行后返回一个结果后执行@AfterThrowing
在方法执行过程中抛出异常的时候执行@Around
环绕通知,可以完成前置统通知和后置通知,使用该注解的方法的入参必须为ProceedingJoinPoint
,ProceedingJoinPoint.process()
执行被切面的方法,可以完成前面四个注解的全部功能。可以看到配置了两个切点,第二个为@Around
使用,第一个被其他通知使用。
@Component
@Aspect
public class AspectLog {
protected Logger logger= LoggerFactory.getLogger(this.getClass());
@Pointcut("execution(public * com.keer.aopdemo.Controller.get1(..))")
public void aspectLog1() {
}
@Pointcut("execution(public * com.keer.aopdemo.Controller.get2(..))")
public void aspectLog2() {
}
@Before("aspectLog1()")
public void doBefore(JoinPoint joinPoint){
List<String> args=new ArrayList<>();
for(Object arg:joinPoint.getArgs()){
args.add((String) arg);
}
logger.info("AOP: 方法前执行");
logger.info("AOP: 方法名:"+joinPoint.getSignature().getName()+",方法参数:"+args.toString());
}
@After("aspectLog1()")
public void doAfter(JoinPoint joinPoint){
logger.info("AOP: 方法结束执行");
}
@AfterReturning("aspectLog1()")
public void doAfterReturn(JoinPoint joinPoint){
logger.info("AOP: 方法执行结束返回结果后执行");
}
@AfterThrowing("aspectLog1()")
public void deAfterThrowing(JoinPoint joinPoint){
logger.info("AOP: 方法抛出异常后执行");
}
@Around("aspectLog2()")
public void doAround(ProceedingJoinPoint joinPoint){
try {
List<String> args=new ArrayList<>();
for(Object arg:joinPoint.getArgs()){
args.add((String) arg);
}
logger.info("AOP: 方法前执行");
logger.info("AOP: 方法名:"+joinPoint.getSignature().getName()+",方法参数:"+args.toString());
joinPoint.proceed();
logger.info("AOP: 方法执行结束返回结果后执行");
}catch (Throwable e){
logger.info("AOP: 方法抛出异常后执行");
}
}
}
3.创建Controller进行测试
该类中创建了两个Web请求方法,第二个使用@Around注解的切点方法,第一个方法是使用其他注解的切点方法。
@RestController
public class Controller {
protected Logger logger = LoggerFactory.getLogger(this.getClass());
@GetMapping("/get1/{name}")
public String get1(@PathVariable String name) {
logger.info("接收到请求:/get1, 数据参数:" + name);
return name + ",welcome to AOP";
}
@GetMapping("/get2/{name}")
public String get2(@PathVariable String name) {
logger.info("接收到请求:/get2, 数据参数:" + name);
return name + ",welcome to AOP";
}
}
访问:http://127.0.0.1:8080/get1/keer,结果如图2:
访问:http://127.0.0.1:8080/get2/keer,结果如图3: