问题描述
我刚刚开始学习Spring。我对一些简单的并发概念感到困惑。
@Service("Class1")
@Data
public class Class1 {
private String uid;
}
@RestController
@RequestMapping("/web")
@Scope("session")
public class Web {
@Autowired
Class1 class1;
@GetMapping("/hello")
public String sayHello(@RequestParam(value = "myName",defaultValue = "World") String name) {
class1.setUid(name);
try{
Thread.sleep(5000);
}
catch (InterruptedException e){
}
return String.format("Hello %s and uid %s!",name,class1.getUid());
}
}
现在,如果我同时使用两个不同的参数myName=name1
和myName=name2
命中两个请求,则两个请求中的uid相同。但是我认为它应该与正在传递的特定名称相同。
我想分配uid
等于要传递的名称。在两个请求中怎么都没有Class1
的2个不同实例?为什么会发生这种并发?
我知道Spring通过生成2个不同的线程来处理2个不同的会话。但是我担心的是两个线程都使用同一个bean。但是我想为不同的会话使用不同的实例。这样做的正确方法是什么?
解决方法
我不确定这是否是问题,但乍一看,我可以将它与默认(隐式使用)作用域为Singleton的事实相关联,这意味着只有一个bean实例(在您的情况下为服务bean)。通常,要处理Bean内部的状态,最好对服务类使用@RequestScope(如果要在其中存储状态),这将为每个特定请求创建Bean实例。
,不确定,但您要在课程级别使用@Service
,以便在所有会话之间共享。因此最终结果取决于以后要处理的请求。
所以
R1 -> "string1"
R2 -> "string2"
您打电话时的时间
return String.format("Hello %s and uid %s!",name,class1.getUid());
它将获取设置的最新值
根据我的理解,数据类不应该是共享组件(@Component
或其派生类),因为默认情况下作用域是单例,您需要更改作用域(原型或其他)。这样它就可以在每次请求时实例化以获取更多详细信息,您可以阅读https://www.geeksforgeeks.org/singleton-and-prototype-bean-scopes-in-java-spring。