面试官:
“我看你简历上写了SpringBoot,那SpringBoot里面会有一些注解,比如@Controller,这个是作什么用的?@Service呢?”
这个问题,如果你只是回答“一个是控制层,一个是业务层”,那是远远不够的。
首先,不管是 @Controller、@Service 还是 @Repository,它们的底层其实都是 @Component。
你可以把它们理解为给类打上的、带不同语义的 “标签”。
它们本质上都是@Component的派生注解,Spring 启动时会执行组件扫描,只要类上带着@Component及其派生注解,就会自动把这个类实例化、管理完整的生命周期,塞进 Spring 的 IoC 容器里,供其他类通过@Autowired/@Resource注入使用,这就是 Spring 核心的 IoC(控制反转)能力。
@Controller
@Controller 作用在控制层。
它的主要任务是负责处理用户发来的 HTTP 请求(如 GET、POST),解析参数,并决定跳转到哪个页面或者返回什么数据。
通常会配合 @RequestMapping 来指定 URL 路由。
@Controller 和 @RestController
@Controller默认返回一个“视图名称”(HTML/JSP 页面)。
如果你想直接回传 JSON 数据,得在方法上加个 @ResponseBody。
而@RestController是 @Controller + @ResponseBody 的组合拳,直接返回 JSON 对象。
@Service
@Service 作用在业务逻辑层。
这里是程序最核心的地方。
所有的计算逻辑、业务判断、多表关联操作都在这里完成。
它位于 Controller 和 Repository 之间,起到了承上启下的作用。
它不关心请求是怎么来的,只关心业务怎么跑。
为什么建议把事务(@Transactional)加在 Service 层而不是 Controller 层?
因为 Service 代表一个完整的业务单元。
比如“转账”,包含扣钱和加钱两个动作,这两个动作必须在一个事务里,要么都成功,要么都失败。
除此之外,@Service的语义化标签,还能让 Spring 的 AOP 切面实现精准切入。
比如我们要给所有业务逻辑加操作日志、权限校验、性能监控,只需要针对@Service注解的类做切面增强即可,完全不用侵入业务代码,这也是分层架构的核心优势。
@Repository 和 @Component
@Repository是持久层标签。
专门用来操作数据库的(DAO 层)。
它有个额外的小功能,能把数据库抛出的原生异常转换成 Spring 的 DataAccessException。
@Component是通用标签。
如果你这个类既不负责接请求,也不写业务逻辑,也不直接操作数据库,它是一个辅助性的、通用的、给三层提供支持的组件,那就用通用的 @Component来标注。
举个用户注册的例子
|
|
梳理一下
| 注解 | 推荐层级 | 主要职责 | 备注 |
|---|---|---|---|
| @Controller | Web层(控制层) | 接收HTTP请求,分发路由,返回视图 | 配合 @ResponseBody 返回数据 |
| @Service | Service层(业务层) | 编写核心业务逻辑,处理事务 | 系统的“大脑” |
| @Repository | DAO层(持久层) | 数据库增删改查 | 自动异常转换 |
| @Component | 任意层 | 通用的组件声明 | 其他三者的“father” |