#java #spring #spring-bean
#java #весна #весенняя фасоль
Вопрос:
Я только начал изучать Spring. Меня смущает какая-то простая концепция параллелизма.
У меня есть класс, содержащий только 1 поле uid
:
@Service("Class1")
@Data
public class Class1 {
private String uid;
}
И у меня есть картограф запросов с Class1
автоматической настройкой в нем.
@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
значение, равное передаваемому имени. Как не может быть 2 разных экземпляра Class1
в обоих запросах? Почему происходит этот параллелизм?
Я знаю, что Spring обрабатывает 2 разных сеанса, генерируя 2 разных потока. Но меня беспокоит то, что оба потока используют один и тот же компонент. Но мне нужен другой экземпляр для разных сеансов. Как правильно это сделать?
Комментарии:
1. Читайте о bean scopes: docs.spring.io/spring-framework/docs/current /…
Ответ №1:
Я не уверен, что это проблема, но на первый взгляд я мог бы связать это с тем фактом, что область действия по умолчанию (неявно используемая) является одноэлементной, что означает, что существует только один экземпляр bean (в вашем случае service bean). Обычно для обработки состояния внутри компонентов лучше использовать @RequestScope для класса service (если вы хотите сохранить там состояние), который будет создавать экземпляр компонента точно для каждого конкретного запроса.
Ответ №2:
Нет уверенности, но вы используете @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 .