java - Spring @Autowired - 实例化新 bean

标签 java spring spring-mvc autowired

在 Spring Autowiring 和作用域方面需要一些帮助。

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

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

  2. CustomHttpClient 被我的应用程序中的多个服务使用。每当我使用 CustomHttpClient 时,我都会通过以下方式 Autowiring 一个实例:

    @Autowired
    private CustomHttpClient httpClient;
    
  3. 我使用拦截器来修改 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 的任何设置时,只要 VM 正在运行,所有其他客户端都会保留新值。因此,当我运行 httpClient.setSomeProperty() 时 - 该设置现在已永久保存。即使我从另一个客户端连接到应用程序。

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

  1. 仍然能够通过拦截器(请求拦截器,通过 进行配置)覆盖 CustomHttpClient 的默认设置。
  2. 确保为每个请求创建一个新的 CustomHttpClient 实例(在拦截器施展魔法之后)。

我尝试将 CustomHttpClient 的范围更改为 @Scope("prototype"),但那样我就无法再使用拦截器更改 CustomHttpClient 的设置。

最佳答案

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

更好的方法是使用单例作用域,使用请求属性或线程局部来将自定义属性传递到请求线程。也就是说,无需在拦截器中修改 HttpClient 属性,只需设置一些请求属性或线程局部变量,并在 CustomHttpClient 类方法中处理这些自定义设置。

关于java - Spring @Autowired - 实例化新 bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18973061/

相关文章:

java - Spring - @Value 返回 null

java - Hibernate session 无法打开事务

Java组播发送者+接收者

java - 在不使用调试参数启动 JVM 的情况下调试 java 应用程序

java - 调用 split 后如何将 header 从父交换复制到子交换?

java - Spring 5 样板项目无法运行

java - 从 Spring Controller 发送 POST 请求

java - 文本框中的文本暂时灰显

java - 使用 eclipselink.media-type 值 : application/json 设置 Marshaller 属性时出现 PropertyException

java.lang.UnsupportedClassVersionError : org/springframework/boot/gradle/plugin/SpringBootPlugin : Unsupported major. 次要版本 52.0