[关闭]
@File 2020-01-17T04:39:09.000000Z 字数 4499 阅读 142

spring-aop 切面配置

java


配置和使用

1. pom.xml 配置

  1. <dependency>
  2. <groupId>org.aspectj</groupId >
  3. <artifactId>aspectjweaver</artifactId >
  4. <version>1.8.7</version >
  5. </dependency>

2. xml配置

...待补全


3. 注解配置

配置开启aop

  1. <!-- beans 属性要引入 xmlns:aop -->
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "
  5. xmlns:aop="http://www.springframework.org/schema/aop">
  6. <!-- 开启注解aop -->
  7. <!-- proxy-target-class:是否基于类代理,true依赖cglib -->
  8. <aop:aspectj-autoproxy proxy-target-class="true"/>
  9. </beans>

@Aspect 声明切面类

  1. // 必须注册
  2. @Component
  3. @Aspect
  4. public class Lidaye{}

@order 顺序权重

@Pointcut 定义切入点

表达式语法
execution 用于匹配符合的方法
within 用于匹配指定的类及其子类中的所有方法
this 匹配可以向上转型为this指定的类型的代理对象中的所有方法
target 匹配可以向上转型为target指定的类型的目标对象中的所有方法
args 用于匹配运行时传入的参数列表的类型为指定的参数列表类型的方法
@annotation 用于匹配持有指定注解的方法
@within 用于匹配持有指定注解的类的所有方法
@target 用于匹配持有指定注解的目标对象的所有方法
@args 用于匹配运行时传入的参数列表的类型持有注解列表对应的注解的方法
通配符
* 匹配任何数量字符
匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数
+ 匹配指定类型的子类型;仅能作为后缀放在类型模式后边
逻辑运算符
&&
||
!
  1. /**
  2. * @param value 切入点表达式
  3. * @param argNames 参数
  4. */
  5. // value = "execution(返回值 包名.类名.方法名(参数))"
  6. @Pointcut("execution(* com.lidaye.*.*(..))")
  7. public void pointcut(){}

@Before 前置通知

  1. /**
  2. * @param value 切入点表达式或切入点方法带()
  3. * @param argNames 参数
  4. */
  5. @Before("pointcut()")
  6. public void before(){}

@AfterReturning 后置通知

  1. /**
  2. * @param value 切入点表达式或切入点方法带()
  3. * @param pointcut 切入点表达式,会覆盖value
  4. * @param returning 返回值
  5. * @param argNames 参数
  6. */
  7. @AfterReturning("pointcut()")
  8. public void afterReturn(){}

@Around 环绕通知

  1. /**
  2. * @param value 切入点表达式或切入点方法带()
  3. * @param argNames 参数
  4. */
  5. @Around("pointcut()")
  6. public Object around(ProceedingJoinPoint pjp){
  7. // 环绕前代码
  8. // 取参数值数组
  9. // Object[] args = pjp.getArgs();
  10. // 取参数名数组
  11. // String[] ageNames = ((CodeSignature) pjp.getSignature()).getParameterNames();
  12. // 执行 前置通知-核心方法-后置通知
  13. Object obj = pjp.proceed();
  14. // 环绕后代码
  15. return obj;
  16. }

@AfterThrowing 异常通知

  1. /**
  2. * @param value 切入点表达式或切入点方法带()
  3. * @param pointcut 切入点表达式,会覆盖value
  4. * @param throwing 异常参数
  5. * @param argNames 参数
  6. */
  7. // 普通形式
  8. @AfterThrowing("pointcut()")
  9. public void afterThrowing(){}
  10. // 获取异常形式
  11. @AfterThrowing(value = "pointcut()", throwing = "exception")
  12. public void afterThrowing(Exception e){}

@After 最终通知

  1. /**
  2. * @param value 切入点表达式或切入点方法带()
  3. * @param argNames 参数
  4. */
  5. @After("pointcut()")
  6. public void after(){}

执行顺序

环绕前 -> 前置 -> 核心方法 -> 环绕后/异常 -> 最终 -> 后置

小案例:通过 AOP 实现统一返回对象 Result

1. 创建 Result 状态码常亮对象

  1. /**
  2. * 结果对象状态码
  3. * @author lidaye
  4. */
  5. public interface ResultCode {
  6. /**
  7. * 成功
  8. */
  9. int SUCCESS_CODE = 200;
  10. /**
  11. * 无权限
  12. */
  13. int UNROOT_CODE = 401;
  14. String UNROOT_MSG = "操作失败,无权限操作";
  15. /**
  16. * 资源请求失败
  17. */
  18. int UNREAD_CODE = 403;
  19. String UNREAD_MSG = "操作失败,资源请求失败";
  20. /**
  21. * 无请求对象
  22. */
  23. int LOSS_CODE = 404;
  24. String LOSS_MSG = "操作失败,资源请求丢失";
  25. /**
  26. * 失败
  27. */
  28. int ERROR_CODE = 500;
  29. String ERROR_MSG = "操作失败,服务器处理异常";
  30. }

2. 创建 Result 对象

  1. /**
  2. * 结果对象
  3. * @author lidaye
  4. */
  5. @Data
  6. public class Result implements Serializable {
  7. private Integer code;
  8. private Object data;
  9. private String msg;
  10. /**
  11. * 成功返回
  12. * @param res 内容
  13. * @return 结果对象(SUCCESS_CODE)
  14. */
  15. public static Result success(Object res) {
  16. return newResult(res, ResultCode.SUCCESS_CODE,null);
  17. }
  18. /**
  19. * 错误返回
  20. * @param msg 错误信息
  21. * @return 结果对象(ERROR_CODE)
  22. */
  23. public static Result error(String msg) {
  24. return newResult(null,ResultCode.ERROR_CODE,msg);
  25. }
  26. public static Result error() {
  27. return error(ResultCode.ERROR_MSG);
  28. }
  29. /**
  30. * 结果丢失
  31. * @param msg 错误信息
  32. * @return 结果对象(LOSS_CODE)
  33. */
  34. public static Result loss(String msg) {
  35. return newResult(null,ResultCode.LOSS_CODE,msg);
  36. }
  37. public static Result loss(){
  38. return loss(ResultCode.LOSS_MSG);
  39. }
  40. /**
  41. * 无权限
  42. * @param msg 错误信息
  43. * @return 结果对象(UNROOT_CODE)
  44. */
  45. public static Result root(String msg) {
  46. return newResult(null,ResultCode.UNROOT_CODE,msg);
  47. }
  48. public static Result root() {
  49. return root(ResultCode.UNROOT_MSG);
  50. }
  51. /**
  52. * 获取结果集对象
  53. * @param res 结果内容
  54. * @param code 结果状态码
  55. * @param msg 提示信息
  56. * @return 结果对象
  57. */
  58. private static Result newResult(Object res, int code, String msg){
  59. Result result = new Result();
  60. result.setCode(code);
  61. result.setData(res);
  62. result.setMsg(msg);
  63. return result;
  64. }
  65. }

3. 设置切面类

  1. @Component
  2. @Aspect
  3. public class ReturnAop {
  4. // 配置影响的方法
  5. @Pointcut("execution(* com.lidaye.pwd.*.controller.*.*(..))")
  6. public void pointcut(){}
  7. // 配置环绕
  8. @Around("pointcut()")
  9. public Result around(ProceedingJoinPoint pjp) {
  10. try {
  11. // 执行 前置通知-核心方法-后置通知
  12. Object obj = pjp.proceed();
  13. // 环绕后代码
  14. return obj != null?
  15. Result.success(obj):
  16. Result.loss();
  17. } catch (Throwable throwable) {
  18. // 异常处理
  19. return Result.error(throwable.getMessage());
  20. }
  21. }
  22. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注