本文介绍了Spring @Autowired - 实例化新bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

需要一些关于Spring自动装配和范围的帮助。

Need some help with Spring autowiring, and scopes.

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

Here is the basic app structure:


  1. 我有一个CustomHttpClient,注释为@Component,还从application.properties文件中提取一些与配置相关的属性(通过@Value注释)。

  1. I have an CustomHttpClient, annotated as @Component, and also pulling some config-related properties from application.properties file (via @Value annotation).

CustomHttpClient由我的应用程序中的多个服务使用。每当我使用CustomHttpClient时,我通过以下方式自动装配该实例:

CustomHttpClient is used by several services in my application. Whenever I'm using the CustomHttpClient, I autowire an instance of that via:

@Autowired
private CustomHttpClient httpClient;


  • 我使用拦截器来修改CustomHttpClient中的一些变量,如下所示:



  • I use interceptor to modify some of the variables inside CustomHttpClient, like so:

    public class MyInterceptor extends HandlerInterceptorAdapter {
    @Autowired CustomHttpClient httpClient;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    httpClient.setSomeProperty(newValue);
    ...
    


  • 现在,这是问题所在。如果我按照上面的描述设置了所有内容,那么每当我通过拦截器更改CustomHttpClient的任何设置时,只要VM正在运行,就会为所有其他客户端保留该新值。因此,当我运行httpClient.setSomeProperty()时 - 该设置现在已永久保存。即使我从另一个客户端连接到该应用程序。

    Now, here is the problem. If I have everything set up as described above, then whenever I change any setting of the CustomHttpClient via interceptor, that new value is persisted for all other clients, as long as VM is running. So when I run httpClient.setSomeProperty() - that setting is now permanently saved. Even if I connect to the application from another client.

    基本上我需要的是两件事:

    Basically what I need to have are two things:


    1. 仍然可以通过拦截器覆盖CustomHttpClient的默认设置(请求拦截器,通过配置)。

    2. 确保为每个创建一个新的CustomHttpClient实例请求(在拦截器执行其魔法之后)。

    我尝试将CustomHttpClient的范围更改为@Scope(prototype),但是这样我就不能再使用拦截器更改CustomHttpClient的设置了。

    I tried changing the scope of CustomHttpClient to @Scope("prototype"), but that way I can no longer change settings of CustomHttpClient with an interceptor.

    推荐答案

    默认情况下使用 @Autowired spring bean范围是单例。这意味着spring会使用 @Autowired 注入相同的单例对象。通过使范围 prototype ,您指示Spring为每个@Autowired注入创建新对象,因此在您的拦截器中将拥有自己的HttpClient副本,并且无法查看其他HttpClient对象。

    By default when you use @Autowired spring bean scope is singleton. That means spring injects the same singleton object where ever you use @Autowired. By making scope prototype you are instructing Spring to create new objects for each @Autowired injection, and so in your interceptor will have its own copy of HttpClient and cant see other HttpClient objects.

    所以更好的方法是使用单例范围,使用请求属性或threadlocal在请求线程中随身携带自定义属性。即不是在拦截器中修改HttpClient属性,只需设置一些请求属性或threadlocals并在 CustomHttpClient 类方法中处理这些自定义设置。

    So better approach is use the singleton scope, Use request attributes or threadlocal to carry around your custom properties down the request thread. ie instead of modifying HttpClient properties in interceptor, just set some request attributes or threadlocals and handle these custom settings within CustomHttpClient class methods.

    这篇关于Spring @Autowired - 实例化新bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    06-19 02:03