假设我有以下Spring MVC控制器
@RestController
@RequestMapping("/books")
public class BooksController {
@Autowired
private final BooksRepository booksRepository;
@RequestMapping(value="/search", method=RequestMethod.POST, consumes="application/json")
public Collection<Book> doSearch(@RequestBody final SearchCriteria criteria) {
return booksRepository.find(criteria);
}
}
以及以下存储库
@Service
public class BooksRepository {
@Autowired
private final JdbcTemplate jdbcTemplate;
@Autowired
private final SearchQueryBuilder searchQueryBuilder;
public Collection<BookLite> find(final SearchCriteria criteria) {
// TODO: will this cause race conditions?
searchQueryBuilder.clear().addKeywords(criteria.getKeywords());
final String query = searchQueryBuilder.buildQuery();
final Object[] params = searchQueryBuilder.buildParams();
return jdbcTemplate.query(query, params, new BookExtractor());
}
}
使用以下SearchQueryBuilder
实现
@Component
public class SearchQueryBuilder {
private final List<String> keywords = new LinkedList<String>();
public SearchQueryBuilder clear() {
keywords.clear();
return this;
}
public SearchQueryBuilder addKeywords(final List<String> keywords) {
for (String keyword : keywords) {
add(keyword);
}
return this;
}
private SearchQueryBuilder add(final String keyword) {
keywords.add(keyword);
return this;
}
public String buildQuery() {
...
}
public Object[] buildParams() {
...
}
}
我的担忧如下。由于SearchQueryBuilder类不是线程安全的,因此以这种方式注入可能会导致竞争条件。处理这个问题的好方法是什么?是否足够(并且是一种良好的做法)将bean范围更改为例如请求?
答案 0 :(得分:1)
我会使用SearchQueryBuilderFactory作为Spring bean,并动态创建SearchQueryBuilder实例。
我会避免创建在执行期间改变状态的Spring bean。
您依赖于使用请求范围会使您的解决方案更加脆弱且容易出错,因为如果您尝试将其用作Web上下文之外的Spring bean,则问题会再次出现。