Spring官网阅读(十八)AOP的核心概念(3)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spring官网阅读(十八)AOP的核心概念(3)

AOP的应用


AOP的实际应用非常多,我这里就给出两个例子

1.全局异常处理器

2.利用AOP打印接口日志


全局异常处理器


需要用到两个注解:@RestControllerAdvice及@ExceptionHandler`,总共分为以下几步:

  1. 定义自己项目中用到的错误码及对应异常信息
  2. 封装自己的异常
  3. 申明全局异常处理器并针对业务中的异常做统一处理


定义错误码及对应异常信息

@AllArgsConstructor
@Getter
public enum ErrorCode {
    INTERNAL_SERVICE_ERROR(500100, "服务端异常"),
    PASSWORD_CAN_NOT_BE_NULL(500211, "登录密码不能为空"),
    PASSWORD_ERROR(500215, "密码错误");
    private int code;
    private String msg;
}
// 统一返回的参数
@Data
public class Result<T> {
    private int code;
    private String msg;
    private T data;
    public static <T> Result<T> success(T data){
        return new Result<T>(data);
    }
    public static <T> Result<T> error(ErrorCode cm){
        return new Result<T>(cm.getMsg);
    }
}

封装对应异常

public class GlobalException extends RuntimeException {
    private static final long serialVersionUID = 1L;
    private int errorCode;
    public CreativeArtsShowException(int errorCode) {
        this.errorCode = errorCode;
    }
    public CreativeArtsShowException(ErrorCode errorCode) {
        super(errorCode.getMsg());
        this.errorCode =  errorCode.getCode();
    }
}

申明异常处理器

//该注解定义全局异常处理类
//@ControllerAdvice
//@ResponseBody
// 使用@RestControllerAdvice可以替代上面两个注解
@RestControllerAdvice
//@ControllerAdvice(basePackages ="com.example.demo.controller") 可指定包
public class GlobalExceptionHandler {
    @ExceptionHandler(value=GlobalException.class) //该注解声明异常处理方法
    public Result<String> exceptionHandler(HttpServletRequest request, Exception e){
        e.printStackTrace();
        // 在这里针对异常做自己的处理
    }
}

其实SpringMVC中提供了一个异常处理的基类(org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler)。我们只需要将自定义的异常处理类继承这个ResponseEntityExceptionHandler然后复写对应的方法即可完成全局异常处理。这个类中的方法很简单,所以这里就不放代码了。


这个类中已经定义了很多的异常处理方法,如下:

@ExceptionHandler({
      HttpRequestMethodNotSupportedException.class,
      HttpMediaTypeNotSupportedException.class,
      HttpMediaTypeNotAcceptableException.class,
      MissingPathVariableException.class,
      MissingServletRequestParameterException.class,
      ServletRequestBindingException.class,
      ConversionNotSupportedException.class,
      TypeMismatchException.class,
      HttpMessageNotReadableException.class,
      HttpMessageNotWritableException.class,
      MethodArgumentNotValidException.class,
      MissingServletRequestPartException.class,
      BindException.class,
      NoHandlerFoundException.class,
      AsyncRequestTimeoutException.class
    })

所以我们只需要复写对应异常处理的方法即可完成自己在当前业务场景下异常的处理。但是需要注意的是,它只会对上面这些框架抛出的异常进行处理,对于我们自定义的异常还是会直接抛出,所以我们自定义的异常处理还是需要在其中进行定义。


接口日志


我们在开发中经常会打印日志,特别是接口的入参日志,如下:

@RestController
@RequestMapping("/test/simple")
@Validated
@Slf4j
public class ValidationController {
    @GetMapping("/valid")
    public String testValid(
            @Max(10) int age, @Valid @NotBlank String name) {
        log.info("接口入参:" + age + "      " + name);
        return "OK";
    }
}

如果每一个接口都需要添加这样一句代码的话就显得太LOW了,基于此我们可以使用AOP来简化代码,按照以下几步即可:

1.自定义一个注解

2.申明切面


定义一个注解

@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Log {
}

申明切面

@Aspect
@Component
@Slf4j
public class LogAspect {
    @Pointcut("@annotation(com.spring.study.springfx.aop.annotation.Log)")
    private void pointcut() {
    }
    @Before("pointcut()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Parameter[] parameters = method.getParameters();
        Object[] args = joinPoint.getArgs();
        String methodName = method.getName();
        Class<?> declaringClass = method.getDeclaringClass();
        String simpleName = declaringClass.getSimpleName();
        StringBuilder sb = new StringBuilder();
        sb.append(simpleName).append(".").append(methodName).append(" [");
        for (int i = 0; i < parameters.length; i++) {
            String name = parameters[i].getName();
            sb.append(name);
            sb.append(":");
            sb.append(args[i]);
            sb.append(";");
        }
        sb.setLength(sb.length() - 1);
        sb.append("]");
        log.info(sb.toString());
    }
}

基于上面的例子测试:

@RestController
@RequestMapping("/test/simple")
@Validated
@Slf4j
public class ValidationController {
    @Log
    @GetMapping("/valid")
    public String testValid(
            @Max(10) int age, @Valid @NotBlank String name) {
        log.info("接口入参:" + age + "      " + name);
        return "OK";
    }
}
// 控制台输出日志:
// ValidationController.testValid [age:0;name:11]

总结


这篇文章到这里就结束啦,这也是《Spring官网阅读笔记》系列笔记的最后一篇。其实整个SpringFrameWork可以分为三部分


1.IOC

2.AOP

3.事务(整合JDBC,MyBatis)

而IOC跟AOP又是整个Spring的基石,这一系列的笔记有10篇以上是IOC相关的知识。AOP的只有这一篇,这是因为Spring简化了AOP的使用,如果要探究其原理以及整个AOP的体系的话必定要深入到源码中去,所以思来想去还是决定将其放到源码阅读系列笔记中去。


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
20天前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
28 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
5天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
14 1
|
2月前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
30天前
|
Java 编译器 Spring
Spring AOP 和 AspectJ 的区别
Spring AOP和AspectJ AOP都是面向切面编程(AOP)的实现,但它们在实现方式、灵活性、依赖性、性能和使用场景等方面存在显著区别。‌
49 2
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
117 9
|
29天前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
43 0
|
2月前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
|
6月前
|
安全 Java Spring
Spring之Aop的底层原理
Spring之Aop的底层原理
|
6月前
|
监控 Java Spring
Spring AOP的作用和底层原理、AOP相关术语
Spring AOP的作用和底层原理、AOP相关术语
87 0
|
6月前
|
设计模式 Java uml
Spring AOP 原理
Spring AOP 原理
35 0