在写这篇文章之前,小编开始背八股文了!!恰逢遇到了Spring AOP的相关内容,仔细回顾下来,发现,对应Spring AOP仅仅局限于: AOP(面向切面编程)就是将那些与业务无关,但是在项目中发挥着不可缺少的作用的代码封装起来,比如:事务,日志,权限等相关的代码,Spring AOP是基于动态代理的方式实现的,如果实现了某个接口,则会基于动态代理的方式实现,如果没有实现接口,则是基于CGLIB代理的方式来实现一个需要代理对象的子类作为代理对象!其实上面这些内容没什么错误!
这是八股文的正常范畴,但是,今日,小编不想再按照八股文来将一大批文字意思了!直接上代码,上案列,来带领大家走进Spring AOP(面向切面编程)!
场景:
假设,我们需要统计某项目中的某些方法的耗时较长的方法,此时就需要我们来统计每个业务方法的执行耗时!直接思路:在每个方法开始执行之前记录当前时间,然后在方法执行结束后在记录当前时间,然后在一相减就是最后的执行耗时!当然,这个想法是没有什么问题的,问题出现在,当这个项目中方法比较少时,所需要修改的代码比较少,但是,当这个项目中的方法比较多,成千上百的时候,所需要更改的代码就显得很繁琐了!这样就得不偿失了!
所以Spring AOP应运而生!
Spring AOP就可以将公共的记录方法开始时间,结束时间的相关代码来进行抽取出来,封装成一个注解类,通过添加注解的方式来实现注入,那么,这样不就显得更加简单了吗?仅仅一个注解就解决了一大串代码的更改!!YYDS
那么,我们所谓的面向切面编程最简单的描述就是:面向一个方法或者多个方法进行编程!(不全面哈!)
实现:动态代理是面向切面编程最主流的实现,而Spring AOP是Spring框架的高级技术,旨在管理Bean对象的过程中,主要通过底层的动态代理机制,对特定的方法进行编程/
导入依赖:在pom.xml文件中导入AOP依赖:
<!-- Spring AOP相关依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
编写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.springframework.stereotype.Component;
@Slf4j
@Component //交给Spring容器进行管理,成为Bean
@Aspect //有这个注解,说明当前类不是普通类,而是AOP类
public class TimeAspect {
@Around("execution(* com.example.controller.*.*(..))") //拦截所有controller包下的所有方法
//当我们需要获取其他包/类下的方法时候,只需要在execution()中添加包/类名即可【支持|| 】
public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis(); //记录开始时间
Object obj = joinPoint.proceed();//调用原始方法运行
long end = System.currentTimeMillis(); //记录结束时间
log.info(joinPoint.getSignature().getName() + "方法运行时间:" + (end - start) + "ms");
return obj; //返回原始方法的返回值
}
}
重新启动程序,运行项目:然后在控制台中就会出现:【当然具体内容还得看您那边调用了哪个类/方法】
然后,大家就会发现,我们并没有修改任何有关项目中的代码,但是却实现了统计各个方法的运行时间!!YYDS啊!!这不就是我们想要的效果吗??
上面统计各个方法的运行时间,仅仅是Spring AOP的小试牛刀,其实Spring AOP不止这一个功能:Spring AOP也能进行记录操作日志,权限控制,事务管理………。
Spring AOP核心概念:
- 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)
- 通知:Advice,指哪些重复的逻辑,也就是共性功能(最终体现为一个方法)
- 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用
- 切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
- 目标对象:Target,通知所应用的对象
Spring AOP的通知类型:
- @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行
- @Before:前置通知,此注解标注的通知方法在目标方法前被执行
- @After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
- @AfterReturning :返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
- @AfterThrowing :异常后通知,此注解标注的通知方法发生异常后执行 </