Understanding Spring Controller Scope and Thread Safety
The article explains why Spring MVC controllers are singleton by default, demonstrates the resulting thread‑unsafe behavior with example code, shows how applying @Scope("prototype") makes them prototype scoped, and provides best‑practice recommendations and a summary of Spring bean scopes.
Spring MVC controllers are singleton by default; using non‑static member variables can cause data logic confusion because the singleton is not thread‑safe.
controller默认是单例的,不要使用非静态的成员变量,否则会发生数据逻辑混乱。正因为单例所以不是线程安全的。
Below is a simple test demonstrating this issue:
package com.riemann.springbootdemo.controller;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author riemann
* @date 2019/07/29 22:56
*/
@Controller
public class ScopeTestController {
private int num = 0;
@RequestMapping("/testScope")
public void testScope() {
System.out.println(++num);
}
@RequestMapping("/testScope2")
public void testScope2() {
System.out.println(++num);
}
}Visiting http://localhost:8080/testScope prints 1; then visiting http://localhost:8080/testScope2 prints 2, showing the singleton controller is not thread‑safe.
Solution: Use Prototype Scope
Adding @Scope("prototype") to the controller makes each request obtain a new instance:
package com.riemann.springbootdemo.controller;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author riemann
* @date 2019/07/29 22:56
*/
@Controller
@Scope("prototype")
public class ScopeTestController {
private int num = 0;
@RequestMapping("/testScope")
public void testScope() {
System.out.println(++num);
}
@RequestMapping("/testScope2")
public void testScope2() {
System.out.println(++num);
}
}Now both /testScope and /testScope2 start with num = 0, each printing 1, confirming prototype scope eliminates the thread‑unsafe behavior.
单例是不安全的,会导致属性重复使用。
Recommendations
Do not define member variables in controllers.
If a non‑static member variable is necessary, annotate the controller with @Scope("prototype") to use prototype scope.
Consider using ThreadLocal variables inside controllers when appropriate.
Supplementary Information: Spring Bean Scopes
Spring defines five main bean scopes:
singleton : one instance per Spring IoC container (eagerly instantiated unless lazy-init is used).
prototype : a new instance is created each time the bean is requested; Spring does not manage the full lifecycle after creation.
request : (web only) a new instance per HTTP request, with Spring still managing the bean thereafter.
session : (web only) a new instance per HTTP session.
global session : (web only) a global session scope similar to the servlet application context.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
