Spring @Autowired – 实例化新bean
需要一些Spring自动assembly和范围的帮助。
这是基本的app结构:
-
我有一个CustomHttpClient,注释为@Component,还从application.properties文件中提取一些与配置相关的属性(通过@Value注释)。
-
CustomHttpClient由我的应用程序中的多个服务使用。 每当我使用CustomHttpClient时,我通过以下方式自动assembly该实例:
@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的任何设置时,只要VM正在运行,就会为所有其他客户端保留该新值。 因此,当我运行httpClient.setSomeProperty()时 – 该设置现在已永久保存。 即使我从另一个客户端连接到该应用程序。
基本上我需要的是两件事:
- 仍然能够通过拦截器覆盖CustomHttpClient的默认设置(请求拦截器,通过配置)。
- 确保为每个请求创建一个新的CustomHttpClient实例(在拦截器执行其魔法之后)。
我尝试将CustomHttpClient的范围更改为@Scope(“prototype”),但这样我就无法再使用拦截器更改CustomHttpClient的设置。
默认情况下,使用@Autowired
spring bean的范围是singleton。 这意味着spring会使用@Autowired
注入相同的单例对象。 通过制作范围prototype
您指示Spring为每个@Autowired注入创建新对象,因此在您的拦截器中将拥有自己的HttpClient副本,并且无法查看其他HttpClient对象。
因此,更好的方法是使用单例范围,使用请求属性或threadlocal在请求线程中随身携带自定义属性。 即,不是在拦截器中修改HttpClient属性,只需设置一些请求属性或threadlocals并在CustomHttpClient
类方法中处理这些自定义设置。
如果你的拦截器只是添加一些属性,那么使用本地线程应该是一个更好的选择。 您可以调用ThreadLocal.set(自定义Map)并将其用于正在运行的线程的任何位置,当程序要离开控制器时,您可以调用ThreadLocal.Unset来清除存储的值。
这样你每次都不需要一个新的HttpcLient实例,每次都是一个新的实例将是一个严重的缺陷。 并且您将能够在正在运行的线程中的任何位置使用自定义地图。
通过XML或注释支持在Spring容器中声明的所有bean都是默认的单例。 如果将具有设置为原型的范围的bean注入单个例如控制器,则它将仅注入一次。 有一种方法可以实现这一目标。 这就是你应该如何声明作为原型的bean。 这意味着每次从容器调用此bean时,容器将始终为您提供一个新实例。
- 什么是@Repository和@Autowired用于。 (弹簧)
- 带有Spring的EJB3
- Spring 4.1 @Qualifier没有工作
- 自动assemblySpring 3.2独立应用程序失败
- Spring构造函数dependency injection – 有和没有自动assembly
- 如何使用Spring手动自动assemblybean?
- 无法自动assembly字段:private org.springframework.security.core.userdetails.UserDetailsService
- 在Spring中,我可以从autowired bean中自动assembly新bean吗?
- 上下文:annotation-config是@AutoWired的替代品吗?