河曲智叟 发表于 2024-11-9 18:41:57

Spring AOP

入门

Spring AOP快速入门:统计各个业务层方法执行耗时
概述
一样平常我们都会想到在方法开始竣事定义一个执行毫秒值计算总耗时,但是这种方法比较繁琐,以是AOP能大大的提高该效率
https://i-blog.csdnimg.cn/direct/d274212ef3a4476c81de2dda17777829.png
思路


[*] 获取方法运行开始时间
[*] 运行原始方法
[*] 获取方法运行竣事时间,计算执行耗时
实现

xml文件

导入依赖:在pomxml中导入AOP的依赖
<dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-aop</artifactId>
</dependency> aop类

编写AOP步伐:针对于特定方法根据业务须要进行编程
@Component
@Slf4j
@Aspect // AOP类
public class TimeAspect {

   @Around("execution(* com.itheima.service.*.*(..))") // 切入点表达式
   public Object aopDemp(ProceedingJoinPoint point) throws Throwable {
       long begin = System.currentTimeMillis();

       //调用原始方法运行
       Object result = point.proceed();

       long end = System.currentTimeMillis();


       log.info(point.getSignature() +"方法执行耗时:{}ms",end - begin);

       return result;
 }
} 使用场景

aop的使用场景远不止如此
比方



[*] 场景
记录操纵日记 ---> 权限控制 ---> 事务管理 .........


[*] 上风
代码无侵入 ---> 减少重复代码 ---> 提高开发效率 ---> 维护方便
AOP核心概念



[*] 连接点:JoinPoint,可以被AOP控制的方法(暗含方法执行时的相关信息)
[*] 关照:Advice,指那些重复的逻辑,也就是共性功能(终极体现为一个方法)
[*] 切入点:PointCut,匹配连接点的条件,关照仅会在切入点方法执行时被应用
[*] 切面:Aspect,描述关照于切入点的对应关系(关照+切入点)
[*] 目标对象:Target,关照全部的对象
https://i-blog.csdnimg.cn/direct/028c285c15654bc6b9819bbe12b39d24.png
AOP关照范例


[*] @Around:围绕关照,此注解标注的关照方法在目标方法前,后都被执行
[*] @Before:前置关照,此注解标注的关照方法在目标方法前被执行
[*] @After:后置关照,此注解标注的关照方法在目标方法后被执行,无论是否有非常都会执行
[*] @AfterReturning:返回后关照,此主角标注的关照方法在目标方法后被执行,有非常不会执行
[*] @AfterThrowing:非常后关照,此注解标注的关照方法发生非常后执行
实现

@Component
@Slf4j
@Aspect //AOP类
public class MyAspect1 {

   @Before(" execution(* com.itheima.service.impl.DeptServiceImpl.*(..)) ") //切入点
   public void before(){
       log.info("前置通知");
 }

   @Around("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
   public Object Around(ProceedingJoinPoint point) throws Throwable {
       Object obj = point.proceed();
       log.info("循环通知");
       return obj;
 }

   @After("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
   public void After(){
       log.info("后置通知");
 }

   @AfterReturning("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
   public void AfterReturning(){
       log.info("AfterReturning");
 }

   @AfterThrowing("execution(* com.itheima.service.impl.DeptServiceImpl.*(..))")
   public void AfterThrowing(){
       log.info("AfterThrowing");
 }



} 注意事项



[*] @Around围绕关照须要本身调用ProceedingJoinPoint.proeed()来让原始方法执行,其他关照不须要思量目标方法执行
[*] @Around围绕关照方法的返回值,必须指定为Object,来接收原始返回值。
@PointCut



[*] 该注解的作用是将公共的切点表达式抽取出来,须要用到时引用该切点表达式即可。
https://i-blog.csdnimg.cn/direct/66b73e9b0da34c8d861d2dfe94e118ce.png
关照顺序

当有多个切面的切入点给都匹配到了目标方法,目标方法运行时,多个关照方法都会被执行
执行顺序

1.差别切面类中,默认按照切面的类名字母排序:


[*] 目标方法前的关照方法:字母排名靠前的先执行
[*] 目标方法后的关照方法:字母排名靠前的后执行
2.用@Order(数字)加在切面类上来控制顺序


[*] 目标方法前的关照方法:数字小的先执行
[*] 目标后的关照方法:数字小的后执行
切入点表达式

   

[*] 切入点表达式:描述切入点方法的一种表达式
[*] 作用:重要用来决定项目中的那些方法须要加入关照
[*] 常见情势:

[*] execution(........):根据方法签名来匹配
[*] @annotation(....):根据注解匹配

@Aspect
@Slf4j
@Component
public class MyAspect6 {

   @Pointcut("execution(public void com.itheima.service.impl.DeptServiceImpl.delete())")
   public void pt(){}
   @Before("pt()")
  public void before(){
       System.out.println("前置通知asdf");
 }

} execution

execution重要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配,语法为:
execution(访问修饰符?返回值 包名.类名.?方法名(方法参数) throws 异常?)

[*] 此中带?的表现可以省略的部分

[*] 访问修饰符:可省略(比如:public、protected)
[*] 包名.类名:可省略
[*] throws非常:可省略(注意是方法上声明抛出的非常,不是实际抛出的非常)

@Pointcut("execution(public void com.itheima.service.impl.DeptServiceImpl.delete())")
  public void before(){
       System.out.println("前置通知asdf");
 }

[*] 可以使用通配符描述切入点

[*] *:单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意范例的一个参数,也可以调配包、类、方法名的一部分
execution(* com.*.service.*.update*(*))
   
[*] .. :多个一连的任意符号,可以通配任意层级的包,或任意范例、任意个数的参数
execution(* com.itheima..DeptService.*(..))


   根据业务须要,可以使用且(&&)、或(||)、非(!)来组合比较复杂的切入点表达式
@annotation



[*] annotation切入点表达式,用于匹配标识有特定注解的方法
实现

MyAspect7
public class MyAspect7 {
   @Pointcut("@annotation(com.itheima.aop.tips)")
   public void pt(){}
   @Before("pt()")
   public void before(){
       System.out.println("前置通知asdf");
 }
} tips
创建一个注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface tips {

} DeptServiceImpl
在该方法下加上本身创建的注解
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
   @Autowired
   private DeptMapper deptMapper;


   @Override
   @tips
   public List<Dept> list() {
       List<Dept> deptList = deptMapper.list();
       return deptList;
 }

   @tips
   @Override
   public void delete(Integer id) {
       //1. 删除部门
       deptMapper.delete(id);
 }
}
​ 连接点



[*] 在Spring中用JoinPoint抽象了连接点,用它可以获取方法执行相关信息,假如目标类名、方法名、方法参数等

[*] 对于@Around关照,获取连接点信息只能使用 ProceedingJoinPoint
[*] 对于其他四种关照,获取连接点信息只能使用JoinPoint,它是ProceedingJoinPoint的父类名


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Spring AOP