The controller is singleton by default, do not use non-static member variables, otherwise data logic confusion will occur. It is not thread-safe because of the singleton.
Let's briefly verify the following:
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);
}
}
We first visited http://localhost:8080/testScope
and the answer was yes 1
; then we visited again http://localhost:8080/testScope2
and the answer was yes 2
.
Get different values, which is not thread safe.
Next, let’s controller
add more cases @Scope("prototype")
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);
}
}
We still visited first http://localhost:8080/testScope
, and the answer was yes 1
; then we visited again http://localhost:8080/testScope2
, and the answer was still 1
.
I believe it is not difficult for everyone to find:
Singletons are not safe and will lead to repeated use of attributes.
solution
1. Do not define member variables in the controller. 2. In case it is necessary to define a non-static member variable, set it to multi-case mode through the annotation @Scope("prototype"). 3. Use ThreadLocal variables in Controller
Supplement
The scope of spring bean has the following 5:
1. singleton: singleton mode, when spring creates an applicationContext container, spring will want to initialize all instances of the scope, plus lazy-init to avoid preprocessing;
2. Prototype: prototype mode, each time the bean is obtained through getBean, a new instance will be generated, and spring will no longer manage it after creation;
(The following is only used under the web project)
3.request: Everyone who engages in the web should understand the domain of the request, that is, a new instance is generated every time a request is made. The difference from the prototype is that after creation, spring is still listening for the next management;
4.session: each session, the same as above;
5. Global session: global web domain, similar to application in servlet.