You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot控制器使用final修饰Service对象是否违反无状态最佳实践?

你的控制器完全符合无状态最佳实践,不属于有状态控制器

Good question! Let's clarify this step by step, since it's a common point of confusion when working with Spring Boot controllers.

First, let's define what makes a controller stateful (and why that's bad):
A stateful controller holds mutable data that changes between requests — things like user-specific session data, request counters, or temporary variables tied to a single request/response cycle that persist across different requests. Since Spring controllers are singletons by default (one instance shared across all requests), any mutable state would cause cross-request contamination, which is a big no-no.

Now, looking at your code:

@RestController
@RequestMapping(value = "/users")
public class UserController {
    final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }
}

This is not stateful — in fact, it's a recommended best practice. Here's why:

  • The userService field is marked final, meaning it can only be assigned once (in the constructor) and will never change for the lifetime of the controller instance.
  • Your UserService (if designed correctly, as most Spring services are) should be a stateless singleton bean. It doesn't hold request-specific data; it delegates to repositories or other stateless components.
  • Since the controller's only field is an immutable reference to a stateless service, there's no mutable state being shared across requests. The controller instance remains safe to reuse for every incoming request.

To contrast, here's an example of a stateful controller that violates best practices:

@RestController
@RequestMapping("/users")
public class BadUserController {
    // This mutable field will be shared across all requests!
    private int requestCount = 0;

    private final UserService userService;

    public BadUserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping
    public List<User> getUsers() {
        requestCount++; // This value will increment for every request, causing cross-request interference
        return userService.getAllUsers();
    }
}

In short: Using final for injected service dependencies is not just safe — it's encouraged. It ensures your dependencies can't be accidentally modified, makes unit testing easier (you can mock the service cleanly), and keeps your controller stateless as required by Spring's best practices.

内容的提问来源于stack exchange,提问作者Tim Hudson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 03:17:39