口试官:Spring Boot 控制层中,@Service 可以完全替换 @Controller 吗?90 ...

打印 上一主题 下一主题

主题 876|帖子 876|积分 2628

作者:毅航
来源:juejin.cn/post/7393533304505204787
在SpringBoot开发中,@Controller和@Service基本上是一样寻常开发中利用的最频繁的两个注解。但你有没考虑过@Service代替@Controller注解来标注到控制层的场景?换言之,经过@Service标注的控制层能否实现将用户哀求分发到服务层的功能?
前言

在SpringBoot开发中,@Controller注解用于标识一个控制器类,该类负责处理惩罚Web哀求。而控制器类通常包罗若干个方法,每个方法对应一个HTTP哀求的处理惩罚逻辑。而控制器是MVC(Model-View-Controller)架构的一部分,其主要负责将用户哀求分发到适当的服务层,并返回视图或响应数据。而@Service注解用于标识一个服务类,用以负责处理惩罚业务逻辑和与数据访问层交互。
信赖对于大多数Java开发者来说@Controller和@Service注解的利用都不算太难。但进一步,用@Service标注控制层能否达到和@Controller注解相同的功能呢?对于这个操作你可能会觉得很疯狂,并下意识的说出不可能。但事实果真如此吗?
我们不妨先通过一个简单的例子来验证一下。
@Sercice代替@Controller

我们起首自定义一个ServiceController的控制层,其内部通过Autowired注解注入一个UserMapper,并通过userMapper来实现控制层与数据层的交互。
Spring Boot 基础就不介绍了,保举看这个实战项目:
https://github.com/javastacks/spring-boot-best-practice
具体代码如下:
ServiceController
  1. @Service
  2. @RequestMapping("/ts")
  3. public class ServiceController {
  4.     @Autowired
  5.     private UserMapper userMapper;
  6.     @GetMapping("get-services")
  7.     @ResponseBody
  8.     public User getServices() {
  9.         User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class)
  10.                 .eq(User::getUsername, "zhangSan"));
  11.         return user;
  12.     }
  13. }
复制代码
然后,通过PostMan发送一个Get哀求,以哀求 http://localhost:8080/ts/get-services 其返回内容如下 :
  1. Date: Sun, 21 Jul 2024 02:37:39 GMT
  2. Keep-Alive: timeout=60
  3. Connection: keep-alive
  4. {
  5.   "username": "zhangSan",
  6.   "id": 1,
  7.   "type": null,
  8.   "remark": "test1"
  9. }
复制代码
通过返回内容,不难看出我们的哀求顺遂到ServiceController的getServices方法。也就是说我们完全可以用@Service来替换@Controller标注在控制层上!
揭秘背后原理

你可能会觉得@Service来替换@Controller这样的操作有的反常规,因为在学习SpringBoot时,从来也没有那个教程告诉我们@Service注解还有这样的骚操作。那@Service可以这样利用的背后缘故原由到底是什么呢?
众所周知,@Service和@Controller注解都能被Spring容器所加载,并注入到Spring容器中。我们以SpringBoot应用为例来分析其注入容器的全过程。
在分析之前我们起首明确一点,对于Spring而言其会根据配置(如 XML 文件或 @ComponentScan 注解)扫描指定的包及其子包,查找标记有 @Controller、@Service、@Repository 和 @Component 的类。但对于Springboot应用而言,其并没有显示的利用XmL配置或@ComponentScan指定扫描路径的方式来加载对应路径下的Bean信息。
这背后的缘故原由主要在于@SpringBootApplication 注解的利用,@SpringBootApplication其实是一个组合注解,其内部包括以下三个注解:

  • @EnableAutoConfiguration: 启用 Spring Boot 的自动配置机制。
  • @ComponentScan: 启用组件扫描,以便自动发现并注册 Spring 组件。
  • @Configuration: 表示这是一个 Spring 配置类。
在默认情况下,Spring Boot 会从主应用类地点的包开始进行组件扫描,这意味着只要 @Controller 和 @Service 注解的类位于主应用类地点包及其子包中,它们就会被自动发现并注册到 Spring 容器中。
明确了SpringBoot对于Bean的加载逻辑后,我们再来深入到其内部来看。SpringBoot对于这部分Bean的加载流程如图所示:

当我们在main方法中实行SpringApplication.run时,其在run方法内容会完成Spring容器的创建,以及Bean的加载。具体来看,其在AbstractApplicationContext中的invokeBeanPostBeanFactoryPostProcessore时,会通过 ConfigurationClassPostProcessor的 postProcessBeanDefinitionRegistry 方法加载路径下所有的bean名称信息,然后在finshBeanFactoryInitialization完成bean的实例化。而我们绕了这么一大圈就是皆在说明,被@Service,@Controller所标注的类在SpringBoot框架中是怎样一步步被注入到容器的。
进一步,笔者曾在揭秘@Controller内部方法与URL绑定的全流程中谈到,对于控制层内的方法,其会在AbstractHandlerMethodMapping中的 afterPropertiesSet()完成哀求url与方法的映射绑定。更进一步,afterPropertiesSet的处理惩罚逻辑全部委托于于 getCandidateBeanNames和processCandidateBean两个方法。
而getCandidateBeanNames 会获取当前容器中所有的bean 的名称集合,并筛选类中标有@Controller大概 @RequestMapping注解的类交给processCandidateBean处理惩罚,以完成哀求url与方法的映射。
此时,我们不妨来回看我们一开始的ServiceController的样例代码:
  1. @Service
  2. @RequestMapping("/ts")
  3. public class ServiceController {
  4.    // ....省略内部细节信息
  5. }
复制代码
不难发现,其虽然没利用@Controller修饰,但其却被@RequestMapping注解信息,也就是说其能被processCandidateBean所处理惩罚,进而其也就能完成url和方法映射关系的维护。更进一步,当哀求至DispatcherServlet时,SpringMVC变更通过其url信息,找到能处理惩罚相应哀求的HandlerMethod。从而也就能完成url的处理惩罚以及视图的渲染。
事实上,只要你能确保Bean信息注入到容器,而且类信息上至少有@Controller大概 @RequestMapping注解,那便能在AbstractHandlerMethodMapping中所解析,然后完成url与方法的绑定!这也就是为什么我们一开始花费精力研究@Controller 和 @Service 注入容器的缘故原由。
总结

在 SpringBoot 开发中,@Controller 和 @Service 是最常用的注解。通常,@Controller 用于标识控制器类,处理惩罚 Web 哀求并将哀求分发到服务层;而 @Service 用于标识服务类,处理惩罚业务逻辑。然而,如果用 @Service 来标注控制层是否可以实现与 @Controller 相同的功能呢?
答案是肯定的。只要类被 @Service 标注,而且包罗 @RequestMapping 等注解,Spring Boot 依然能够将其作为控制器来处理惩罚哀求并返回响应。这背后的原理在于 @Service 和 @Controller 都能被 Spring 容器加载和注册,而且 @RequestMapping 注解能够使类的方法与 URL 映射,从而实现哀求处理惩罚功能。
更多文章保举:
1.Spring Boot 3.x 教程,太全了!
2.2,000+ 道 Java口试题及答案整理(2024最新版)
3.免费获取 IDEA 激活码的 7 种方式(2024最新版)
觉得不错,别忘了随手点赞+转发哦!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

万有斥力

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表