湖南茶叶网站建设,简单去除wordpress主题版权,网站设计联盟,seo公司优化方案目录
1. 以增加方法执行时间为例使用AOP
1.1 引入AOP依赖
1.2 编写AOP程序
2. AOP的重要概念
3. AOP通知类型与通知方法标注
3.1 在通知方法前使用对应注解
3.2 使用Pointcut注解提取公共切点表达式
3.3 跨类使用切点
3.4 切面类排序 1. 以增加方法执行时间为例使用AO…目录
1. 以增加方法执行时间为例使用AOP
1.1 引入AOP依赖
1.2 编写AOP程序
2. AOP的重要概念
3. AOP通知类型与通知方法标注
3.1 在通知方法前使用对应注解
3.2 使用Pointcut注解提取公共切点表达式
3.3 跨类使用切点
3.4 切面类排序 1. 以增加方法执行时间为例使用AOP
1.1 引入AOP依赖
在pom.xml中增加关于AOP的配置 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactId/dependency
1.2 编写AOP程序
以图书管理系统为例为每个方法增加耗时计算与日志打印。
创建aspect包在其下创建TimeAspect类
package com.example.bookmanagementsystem.aspect;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;Aspect
Slf4j
Component
public class TimeAspect {Around(execution(* com.example.bookmanagementsystem.controller.*.*(..)))public Object timeCost(ProceedingJoinPoint joinPoint) throws Throwable {long startSystem.currentTimeMillis();// 执行目标方法Object resultjoinPoint.proceed();long endSystem.currentTimeMillis();log.info(joinPoint消耗时间(end-start)ms);return result;}
}关于注解
1、Aspect表示该类是一个切面类
2、Around用于指明切面类的作用域与作用方式在哪个环节对哪些方法
关于切面类成员方法
1、timeCost方法的参数是一个ProceedingJoinPoint类型的对象表示目标方法
2、代码被分为三大部分 2. AOP的重要概念
1、切点一组通过表达式描述的规则
2、连接点切面作用/描述的方法即被AOP控制的目标方法
3、通知具体要做处理的逻辑
4、切面切点通知即切面一个类可以有多个切面
以上述切面类为例 3. AOP通知类型与通知方法标注
1、Around环绕通知此注解标注的通知方法在目标方法前、后都被执行最常用
2、Before前置通知此注解标注的通知方法在目标方法前被执行
3、After
后置通知此注解标注的通知方法在目标方法后被执行无论是否发生异常都会执行
4、AfterReturning
返回后通知此注解标注的通知方法在目标方法后被执行有异常不会执行
5、AfterThrowing异常后通知此注解标注的通知方法在异常后被执行
3.1 在通知方法前使用对应注解
现在controller包下创建一个HelloController类编写方法作为目标方法
由于AfterReturning与AfterThrowing标注的方法在异常发生与否时返回不同故编写两个方法使其满足一个正常运行一个运行时报异常
package com.zhouyou.demos.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
public class HelloController {RequestMapping(/test1)public String test1(){return hello;}RequestMapping(/test2)public int test2(){return 10/0;}
}在aspect包下创建TestAspect类用于编写通知方法
package com.zhouyou.demos.aspect;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;Aspect
Slf4j
Component
public class AspectDemo {Around(execution(* com.zhouyou.demos.controller.*.*(..)))public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {log.info(AspectDemo around 前);Object resultjoinPoint.proceed();log.info(AspectDemo around 后);return result;}Before(execution(* com.zhouyou.demos.controller.*.*(..)))public void doBefore(){log.info(AspectDemo before);}After(execution(* com.zhouyou.demos.controller.*.*(..)))public void doAfter(){log.info(AspectDemo after);}AfterReturning(execution(* com.zhouyou.demos.controller.*.*(..)))public void doAfterReturning(){log.info(AspectDemo afterReturning);}AfterThrowing(execution(* com.zhouyou.demos.controller.*.*(..)))public void doAfterThrowing(){log.info(AspectDemo afterThrowing);}
}启动项目依次根据路由映射访问test1方法和test2方法可查看日志观察通知方法执行顺序 3.2 使用Pointcut注解提取公共切点表达式
上述使用方法中在使用对应注解标注通知方法时需要重复编写公共切点表达式这很不方便
可使用Pointcut提取公共切点表达式在后续使用公共切点表达式时则直接使用Pointcut标注的方法名即可
修改3.1中的代码
package com.zhouyou.demos.aspect;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;Aspect
Slf4j
Component
public class AspectDemo {Pointcut(execution(* com.zhouyou.demos.controller.*.*(..)))private void pc(){}Around(pc())public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {log.info(AspectDemo around 前);Object resultjoinPoint.proceed();log.info(AspectDemo around 后);return result;}Before(pc())public void doBefore(){log.info(AspectDemo before);}After(pc())public void doAfter(){log.info(AspectDemo after);}AfterReturning(pc())public void doAfterReturning(){log.info(AspectDemo afterReturning);}AfterThrowing(pc())public void doAfterThrowing(){log.info(AspectDemo afterThrowing);}
}3.3 跨类使用切点
现在aspect包中再创建一个切面类aspectDemo2以Before为例使用aspectDemo的切点。
package com.zhouyou.demos.aspect;import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;Aspect
Slf4j
Component
public class AspectDemo2 {Before(com.zhouyou.demos.aspect.AspectDemo.pc())public void doBefore(){log.info(AspectDemo2 doBefore);}
}
启动项目根据方法路由映射即可在日志处观察到通知方法的具体执行顺序情况
使用方法注意事项
1在跨类使用公共切点时需要使用全限定类名
2在当前类中若在其类中实现的切点需要在其他类中使用则切点必须以public修饰。
使用private修饰的切点只能在当前类中使用
3.4 切面类排序
现aspect包下由AspectDemo、AspectDemo1、AspectDemo2三个切面类并在每个切面类中实现Before通知和After通知。
创建目标方法并指定路由映射并进行访问查看日志输出 在采取默认排序的情况下默认采取按照切面类的类名字母排序
对于Before通知排名越靠前的先执行
对于After通知排名越靠后的先执行
但这并不便于管理Spring提供了Order注解用于给切面类设置优先级
对于Before通知Order中的数字越小越先执行
对于After通知Order中的数字越大越先执行
现对AspectDemo切面类使用Order(3)、AspectDemo1切面类使用Order(2)、AspectDemo2切面类使用Order(1)启动程序查看日志输出