面向切面编程是在Spring boot 当中经常用到的一种思想,常常用于日志的记录,还有一些测试运行时间等,面向切面编程的底层其实是动态代理的思想,通过动态代理加强原方法,例如在原先的方法中添加一些新的功能,就可以通过AOP实现,下面通过一些简单的案例来熟悉一下AOP。
第一步在pom.xml中导入AOP编程的依赖。
<!-- 引入aop支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
导入成功后 编写一个测试某些方法运行时间的功能
package com.woklio.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Slf4j//日志记录注解
@Component//注册成为Bean对象,交给Spring统一管理
@Aspect//把该类标记成一个切面类
public class TimeAspect {
//设置切入点,对哪些方法切入
@Pointcut("execution(* com.woklio.service.*.*(..)) || execution(* com.woklio.controller.*.*(..)) ")//切入点表达式com.woklio.service下所有的类以及所有方法和所有参数,要小写
void pt(){}
@Around("pt()")//这里设定切入方法的通知类型
public Object recordAspect(ProceedingJoinPoint pjp ) throws Throwable {
long begin = System.currentTimeMillis();
Object result = pjp.proceed();//原方法运行在这里可以返回的是原方法返回的对象,在这里可以对返回的对象进行修改
//result = null;如果执行这句代码会导致被切入的方法返回值全变成null
long end =System.currentTimeMillis();
log.info(pjp.getSignature()+"执行时间:{}ms",end-begin);
return result;
}
}
通知类型有三种,分别是@Before 切入方法执行前的通知,在被切入的方法执行前运行切入方法@After 切入方法执行后的通知,在被切入的方法执行后运行切入方法,@Around 则是环绕通知,将被切入方法变成一个类似于被调用的一个方法,也是最常见的通知,只有环绕通知需要传入参数这里的pjp对象是切入点,个人理解为把程序当初一根香蕉并在被切入方法的头尾处的位置切开,在这两个切面位置添加一下东西,例如给这两个香蕉切面沾点面包糠煎一下?
这里还有其他方法来设置切入点表达式,MyGo是自定义注解
@Pointcut("@annotation(com.woklio.aop.MyGo)")//将切入点表达式改为这个
package com.woklio.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)//元注解,设置被注解的注解的生命周期,这里是RUNTIME,JVM加载完class文件后依然存在
@Target(ElementType.METHOD)//元注解,设置被注解的注解的作用对象,METHOD指方法
public @interface MyGo {
}
只需要在需要被切入的方法名上加入@MyGo注解即可。