Loading...

面试官:SpringBoot里面会有一些注解,比如@Controller,这个是作什么用的?@Service呢?

阅读 ...

面试官:

“我看你简历上写了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来标注。

举个用户注册的例子

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 1. Controller层:负责接活
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public String register(@RequestBody User user) {
        // 校验一下基本参数,然后丢给Service
        return userService.registerUser(user);
    }
}

// 2. Service层:负责干活(核心逻辑)
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    
    // 注入密码加密器
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Transactional // 保证业务原子性
    public String registerUser(User user) {
        // 1. 判断用户名是否存在
        if(userRepository.existsByName(user.getName())) {
            return "用户已存在";
        }
        
        // 2. 密码加密:绝对不能存明文!
        // BCrypt会自动生成随机盐值,每次加密结果都不一样,但验证时能匹配
        String encryptedPassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encryptedPassword);
        
        // 3. 保存到数据库
        userRepository.save(user);
        return "注册成功";
    }
}


// 3. Repository层:负责和数据库打交道
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // Spring Data JPA会自动实现这个方法,根据用户名判断是否存在
    boolean existsByName(String name);
}

梳理一下

注解 推荐层级 主要职责 备注
@Controller Web层(控制层) 接收HTTP请求,分发路由,返回视图 配合 @ResponseBody 返回数据
@Service Service层(业务层) 编写核心业务逻辑,处理事务 系统的“大脑”
@Repository DAO层(持久层) 数据库增删改查 自动异常转换
@Component 任意层 通用的组件声明 其他三者的“father”
本文由 iamxurulin 原创发布,转载请保留原文链接。
最后更新于 2026-08-23 17:21:42
关于作者与文章

本文为 iamxurulin 原创技术文章。如对内容有疑问或建议,欢迎在评论区交流讨论。

Coder_Studio - 记录后端开发、算法与 AI 的成长之路