不能用常理的角度!来理解这篇SpringBoot自动装配原理,真独特啊~

在这里插入图片描述

前言

看了标题后,你应该能猜到我不是要从源码角度分析 SpringBoot 自动装配原理。再分析源码那也太没劲了,写文章很麻烦的,写一个很多人写过的文章更麻烦(但我依旧建议先了解原理,再找机会应用到项目中)【白嫖资料】

我想记录的其实是:我在项目中无意间使用了SpringBoot的自动装配,做了一个 SpringBoot 自动装配的实战案例。

先说一下这个“无意间”的事件发生背景吧!作为一个后端程序员,对于接口入参的字段校验那是家常便饭,所以对校验非空的注解常用 @NotNull,字段为空会抛出 MethodArgumentNotValidException 异常,就是下面这一长串。

{
	"timestamp": "2021-07-02T02:12:29.868+0000",
	"status": 400,
	"error": "Bad Request",
	"errors": [
		{
			"codes": [
				"NotNull.loginDTO.password",
				"NotNull.password",
				"NotNull.java.lang.String",
				"NotNull"
			],
			"arguments": [
				{
					"codes": [
						"loginDTO.password",
						"password"
					],
					"arguments": null,
					"defaultMessage": "password",
					"code": "password"
				}
			],
			"defaultMessage": "密码不能为空",
			"objectName": "loginDTO",
			"field": "password",
			"rejectedValue": null,
			"bindingFailure": false,
			"code": "NotNull"
		}
	],
	"message": "Validation failed for object='loginDTO'. Error count: 1",
	"path": "/v1/test/login"
}

但是我的固搭前端小伙伴只想要 @NotNull(message=“自定义异常”)里的 message 内容;所以我每次都会在项目中定义一个全局异常处理,一旦发生 MethodArgumentNotValidException 异常,就捕捉处理,如下面这样子的:

{
	"code": 400,
	"msg": "password:密码不能为空",
	"data": 0
}

以前我每个项目都要写这个全局异常处理,烦得很!恰巧最近在搭建 maven 私服,我就想将这块功能写到我的 maven 私服中,以后只要在 pom 文件中依赖我的 maven,我都不用写了。

接下来就是我的实现步骤了,看我如何一步步“被逼”使用了 SpringBoot 的自动装配。

项目搭建发布

首先在 maven 项目中添加一个全局异常处理类 ValidParamExceptionHandler ,负责接口入参非空验证的异常处理。

@ControllerAdvice
public class ValidParamExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public ApiResponse handlerMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        StringBuilder errorMessage = new StringBuilder(bindingResult.getFieldErrors().size() * 16);
        for (int i = 0; i < bindingResult.getFieldErrors().size(); i++) {
            if (i > 0) {
                errorMessage.append(",");
            }
            FieldError fieldError = bindingResult.getFieldErrors().get(i);
            errorMessage.append(fieldError.getField());
            errorMessage.append(":");
            errorMessage.append(fieldError.getDefaultMessage());
        }
        return new ApiResponse(400,errorMessage.toString(),0);
    }
}

如果此时我直接打包发布并在新的项目中引入这个 maven 的依赖,你觉得新的项目中会做全局异常处理吗?我第一次就是原封不动的操作了一遍,结果就是不行!!!于是我在想,是因为 ValidParamExceptionHandler 类没有被 Spring 扫描到?那我加一个 @Component 注解不就可以了吗?但是当我打开 @ControllerAdvice 注解,我就知道我在想屁吃,因为 @ControllerAdvice 中已经包含了 @Component 注解。
在这里插入图片描述
最后我上网搜索解决方式,看到了如下解决方案,即在 resources 文件夹下面的 META-INF 新建一个spring.factories 文件,并写入如下内容【白嫖资料】

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.xinmachong.exception.ValidParamExceptionHandler

第一行是固定的,第二行显然就是全局异常处理类的路径。

最后打包发布。

扫描二维码关注公众号,回复: 14573199 查看本文章

全局异常测试

写一个测试接口如下图所示:
在这里插入图片描述
其中 LoginDTO 是:

@Data
public class LoginDTO {
    @NotNull(message = "账号不能为空")
    private String account;
    @NotNull(message = "密码不能为空")
    private String password;
}

测试接口的过程和结果如下图所示:
在这里插入图片描述
入参只有一个 account,请求后看到返回信息为:“password:密码不能为空”。当时的内心就是两个字—握草;因为这个全局异常处理在新项目中竟然生效了。

总结

做的时候没有多想原理,但实现之后我肯定要弄明白的啊,所有人都知道了,关键点就在 spring.factories;但是为啥 spring.factories 这个文件这么屌?突然想起来之前看的 SpringBoot 自动装配实现的源码中好像有提到这个,通过查证,在源码的最后找到了 spring.factories。

一瞬间我突然理解了,原来这个就是通过 SpringBoot 自动装配实现了全局异常处理类的生效!豁然开朗。

最后,祝大家早日学有所成,拿到满意offer,快速升职加薪,走上人生巅峰

可以的话 请给我一个三连支持一下哟???【白嫖资料】

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_37929553/article/details/118493609