上周文章年轻人不讲武德,竟然重构出这么优雅后台 API 接口我们使用 @ControllerAdvice
与 ResponseBodyAdvice
重构后端的 API 接口,降低了复杂度,减少了重复代码,后续接口开发非常简洁优雅。
知其然而知其所以然,今天这篇文章来聊聊这个注解背后的原理,让我们彻底掌握这个注解,避免后续踩坑。
另外,有个小伙伴看完上篇文章,觉得这个注解的跟 Spring Interceptor
功能很类似,再加上之前还学习了 Servlet
体系 Filter
功能,不知道这几个有什么区别,感觉很混乱。
所以今天这篇文章下面两个部分出发,详细解释一下。
@ControllerAdvice
与ResponseBodyAdvice
注解原理Filter
,Interceptor
,ResponseBodyAdvice
区别
从源码解析背后的原理
上篇文章中我们看到 ResponseBodyAdvice
的子类使用 @ControllerAdvice
注解,大家有没有好奇,如果我将@ControllerAdvice
换成 @Controller
注解,还能达到上篇文章的效果吗?
感兴趣的小伙伴可以自己尝试下,这里阿粉自己告诉大家结果了,实际测试结果是不行的。
那为什么一定要与@ControllerAdvice
搭配才会生效?
首先我们先查看一下 @ControllerAdvice
的源码:
image-20201128152447563
可以看到这个注解上还存在一个我们非常熟悉的 @Component
注解。这里我们可以将 @ControllerAdvice
理解成@Component
子类,所以其修饰的类也会成为 Spring 中 Bean
。
ps:大家可以看下
@Controller
/@Service
/@Repository
,其实也是这个原理。
Spring 容器初始化过程,如果扫描到 @ControllerAdvice
注解,将会将其生成一个 ControllerAdviceBean
Bean。
这个过程代码主要位于 RequestMappingHandlerAdapter#initControllerAdviceCache
:
这段代码主要分为两步:
第一步使用 ControllerAdviceBean#findAnnotatedBeans
获取所有被 @ControllerAdvice
修饰的类。
第二步将所有实现了ResponseBodyAdvice
接口的 Bean 放入到 requestResponseBodyAdviceBeans
集合中,后续将会使用该集合。