企业网站开发成都,营销网页,班级文化墙设计图片,h5手机网站源码下载AOP切面编程的最佳应用场景
记录日志性能监控事务管理处理异常数据验证#xff0c;验证传入参数的正确性#xff08;一般不用这个方法做#xff0c;而是用拦截器#xff09; spring提供了以下注解供开发者使用#xff0c;编写AOP程序 Aspect 申明切面Pointcut 切点#…AOP切面编程的最佳应用场景
记录日志性能监控事务管理处理异常数据验证验证传入参数的正确性一般不用这个方法做而是用拦截器 spring提供了以下注解供开发者使用编写AOP程序 Aspect 申明切面Pointcut 切点申明AOP的作用范围如一个类下所有方法某个方法带有指定注解的方法Before 前置通知After 后置通知Around 环绕通知AfterThrowing 异常通知当被切入点中代码执行异常时触发 实操
举个例子
定义RestController
RequestMapping(path {test})
public class DemoController {GetMapping(path {test01/{name}})public ResponseEntityString test01(PathVariable(name) String name) {return new ResponseEntity(name.toUpperCase(), HttpStatus.OK);}
}如果我希望在上面方法使用AOP定义一个类实现如下Slf4j
Aspect
Component
public class AOPAction {// 定义切点标记此切点在什么范围内此切面起作用Pointcut(execution(* com.train.controller.DemoController.test02(..)))public void pointcut() {}//前置通知Before(value pointcut())public void before(JoinPoint joinPoint) {log.info(Before Method : {}...{}, joinPoint.getSignature().getName(), args[0].toString());}// 后置通知After(value pointcut())public void after(JoinPoint joinPoint) {log.info(After Method : {}...{}, joinPoint.getSignature().getName(), args[0].toString());}// 环绕通知Around(value pointcut())public Object around1(ProceedingJoinPoint joinPoint) throws Throwable {log.info(Around 1 Method before: {}..., joinPoint.getSignature().getName());Object result joinPoint.proceed();log.info(Around 1 Method after: {}..., joinPoint.getSignature().getName());return result;}
}切点执行范围
此章节介绍多种切点定义形式开发中使用哪一种视情况而定
1.指定包下所有类的所有方法
应用在此包下所有类的所有方法上
// 包名:com.train.controller
Pointcut(execution(* com.train.controller..*.*(..)))
public void pointcut() {}2.指定类中所有方法
应用在指定类的所有方法上
// 全类名:com.train.controller.DemoController
Pointcut(execution(* com.train.controller.DemoController.*(..)))
public void pointcut() {}3.指定某个类中某个方法
应用在指定类的指定方法上而此类中的其他方法不会被应用
// 全类名:com.train.controller.DemoController
Pointcut(execution(* com.train.controller.DemoController.test01(..)))
public void pointcut() {}4.1 按参数数量指定
AOP切入点表达式规范中用*表示一个参数用…表示无固定个数参数
可以这么理解把*理解成通配符且仅匹配一个。
// 仅作用在com.train.controller包下所有类中仅有2个参数的方法上
Pointcut(value execution(* com.train.controller..*.*(*,*)))
public void pointcut02(){}
// 仅作用在com.train.controller包下所有类中仅有5个参数的方法上
Pointcut(value execution(* com.train.controller..*.*(*,*,*,*,*)))
public void pointcut02(){}4.2 按参数注解指定 ⚠️ 研究中未完成 5.加有指定注解的方法
仅应用在使用了注解的方法上可以使用自定义注解也可以使用框架提供注解。此形式最灵活推荐开发中使用
// 自定义注解
public interface LogPointCut {}
// 加注解的方法
GetMapping(path {test/{name}})
LogPointCut
public ResponseEntityString test(PathVariable(name) String name) {return new ResponseEntity(name.toUpperCase(), HttpStatus.OK);
}
// 定义
Pointcut(annotation(com.train.annotation.LogPointCut))
public void pointcut() {
}6.组合条件【难点】
使用A符合 Spring AOP 的切入点表达式规范组合多个条件组合条件最好用连接各个条件。用匹配接口。用*匹配一个。用…匹配无固定数
举例
// 仅作用在com.train.controller包下所有类中所有标记了LogPointCut注解的方法上
Pointcut(value execution(* com.train.controller..*.*(..)) annotation(com.train.spr.annotation.LogPointCut))
public void pointcut02(){}// 仅作用在com.train.spr.controller包下所有实现了MyInterface接口的类的方法上
Pointcut(value execution(* (com.train.controller..* com.train.spr.interfaces.MyInterface).*(..)))
public void pointcut02(){}// 仅作用在com.train.spr.controller包下所有实现了MyInterface接口和MyInterface2接口的类的方法上
Pointcut(value execution(* (com.train.controller..* com.train.spr.interfaces.MyInterface com.train.spr.interfaces.MyInterface2 ).*(..)))
public void pointcut02(){}当然也可以组合多个已定义的条件作为一个条件例如
import org.aspectj.lang.annotation.Pointcut;// 仅作用在com.train.spr.controller包下类的方法上
Pointcut(value execution(* com.train.controller..*.*(..)))
public void pointcut01() {}// 仅作用在实现了MyInterface接口的类的方法上
Pointcut(value execution(* com.train.spr.interfaces.MyInterface.*(..)))
public void pointcut02() {}// 组合上述两个切入点的条件
Pointcut(value pointcut02() pointcut01())
public void pointcut03() {}AOP切入点表达式规范请查阅官网 获取参数
AOP的方法可以获取被切入方法的参数但是修改这些参数并不会在被切入方法中生效。举个例子方法A有一个前置通知方法B且方法B获取方法A的参数即便方法B中修改了参数值方法A获取到的参数仍然不会改变原来是怎样就是怎样
获取参数这块注意3点就够了。
前置通知/后置通知的参数是org.aspectj.lang.JoinPoint环绕通知的参数是org.aspectj.lang.ProceedingJoinPoint被切入点的参数信息都被封装到JoinPoint或ProceedingJoinPoint中直接从中获取即可【注意类型】
特殊的切入方法——异常通知
研究中未完成