在Spring Autowiring 和范围方面需要一些帮助。

这是基本的应用程序结构:

  • 我有一个CustomHttpClient,注释为@Component,还从application.properties文件中提取了一些与配置相关的属性(通过@Value注释)。
  • CustomHttpClient由我的应用程序中的多个服务使用。每当我使用CustomHttpClient时,都会通过以下方式自动为其连接一个实例:
    @Autowired
    private CustomHttpClient httpClient;
    
  • 我使用拦截器修改CustomHttpClient内部的一些变量,如下所示:
    public class MyInterceptor extends HandlerInterceptorAdapter {
    @Autowired CustomHttpClient httpClient;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    httpClient.setSomeProperty(newValue);
    ...
    

  • 现在,这就是问题所在。如果我如上所述进行了所有设置,则只要我通过拦截器更改CustomHttpClient的任何设置,只要虚拟机正在运行,该新值就会对所有其他客户端保持不变。因此,当我运行httpClient.setSomeProperty()时,该设置现在将被永久保存。即使我从另一个客户端连接到应用程序。

    基本上,我需要做两件事:
  • 仍然能够通过拦截器(请求拦截器,通过配置)覆盖CustomHttpClient的默认设置。
  • 确保为每个请求创建一个新的CustomHttpClient实例(在拦截器执行其魔术之后)。

  • 我尝试将CustomHttpClient的范围更改为@Scope(“prototype”),但是那样一来,我将无法再使用拦截器更改CustomHttpClient的设置。

    最佳答案

    默认情况下,当您使用@Autowired时,spring bean的作用域是单例。这意味着spring会在您使用@Autowired的任何地方注入(inject)相同的单例对象。通过将作用域设置为prototype,您将指示Spring为每个@Autowired注入(inject)创建新对象,因此在您的拦截器中将拥有自己的HttpClient副本,而看不到其他HttpClient对象。

    因此,更好的方法是使用单例作用域,使用请求属性或threadlocal在请求线程中携带自定义属性。即,不要在拦截器中修改HttpClient属性,而只需设置一些请求属性或threadlocals并在CustomHttpClient类方法中处理这些自定义设置即可。

    10-08 17:09