Недавно я столкнулся с проблемой состояния гонки из-за объявления переменной экземпляра внутри класса обслуживания по умолчанию в области действия (синглтон).Цель переменной экземпляра состояла в том, чтобы сделать мой код более читабельным и избежать постоянной передачи одной и той же переменной разным частным методам в классе Service.Пример звучит так:
@Service
public class SomeServiceImpl implements SomeService {
private final StatusRepository statusRepository;
private Predicate<Status> statusPredicate;
@Autowired
public SomeServiceImpl(StatusRepository statusRepository) {
this.statusRepository = statusRepository;
}
@Override
public List<Status> getAllowedStatuses(String userId) {
statuses = statusRepository.getAll();
initPredicate();
appendPredicateA();
appendPredicateB();
List<Status> results = statuses.stream()
.filter(statusPredicate)
.collect(Collectors.toList());
return results;
}
private void initPredicate() {
statusPredicate = p -> p.getDefault().equals("default");
}
private void appendPredicateA() {
statusPredicate.and(p -> p.getA().equals("A"));
}
private void appendPredicateB() {
statusPredicate.and(p -> p.getB().equals("B"));
}
}
Это очень простой пример того, чего я хочу достичь.Это явно не потокобезопасно, потому что теперь класс обслуживания находится в состоянии.Я мог бы просто решить эту проблему, превратив переменную statusPredicate в локальную переменную, и методы void возвращают предикат после того, как он былдобавлены новые условия, но они будут загромождены следующим образом:
@Override
public List<Status> getAllowedStatuses(String userId) {
statuses = statusRepository.getAll();
Predicate<Status> statusPredicate = p -> p.getDefault().equals("default");
statusPredicate = appendPredicateA(statusPredicate);
statusPredicate = appendPredicateB(statusPredicate);
List<Status> results = statuses.stream()
.filter(statusPredicate)
.collect(Collectors.toList());
return results;
}
Было бы постоянно вызывать изменение переменной и возвращать переменную.
Я знаю несколько решений, которые могут решитьнапример, добавление @ RequestScope к классу Service, чтобы каждый запрос от HTTP получал новый экземпляр объекта Service, или использование ThreadLocal в переменной Predicate.Тем не менее, я не совсем уверен, каков наилучший подход и можно ли с самого начала объявить переменную экземпляра в классе Service.Если с самого начала плохо делать класс Service с состоянием, как мне структурировать свой код, чтобы он был чище и при этом оставался без состояния?
Пожалуйста, сообщите!Заранее спасибо: D