Java Spring@Autowired-实例化新bean
需要一些关于Spring自动布线和范围的帮助 以下是应用程序的基本结构:Java Spring@Autowired-实例化新bean,java,spring,spring-mvc,autowired,Java,Spring,Spring Mvc,Autowired,需要一些关于Spring自动布线和范围的帮助 以下是应用程序的基本结构: 我有一个CustomHttpClient,注释为@Component,还从application.properties文件(通过@Value注释)中提取一些与配置相关的属性 CustomHttpClient由我的应用程序中的多个服务使用。每当我使用CustomHttpClient时,我都会通过以下方式自动连接该客户端的实例: @Autowired private CustomHttpClient httpClient;
@Autowired
private CustomHttpClient httpClient;
public class MyInterceptor extends HandlerInterceptorAdapter {
@Autowired CustomHttpClient httpClient;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
httpClient.setSomeProperty(newValue);
...
我尝试将CustomHttpClient的作用域更改为@scope(“prototype”),但这样我就无法再使用拦截器更改CustomHttpClient的设置。如果拦截器只是添加一些属性,那么使用线程本地应该是更好的选择。您可以调用ThreadLocal.set(自定义映射)并在运行线程的任何地方使用它,当程序将离开控制器时,您可以调用ThreadLocal.Unset,这将清除存储的值
这样,您就不需要每次都需要一个新的HttpcLient实例,而且每次都需要一个新实例也是一个严重的缺陷。您可以在运行线程中的任何位置使用自定义映射。默认情况下,当您使用
@Autowired
时,Springbean的作用域为singleton。这意味着spring将在您使用@Autowired
时注入相同的单例对象。通过制作scopeprototype
,您指示Spring为每个@Autowired注入创建新对象,因此在您的拦截器中将有自己的HttpClient副本,并且看不到其他HttpClient对象
所以更好的方法是使用singleton作用域,使用请求属性或threadlocal在请求线程中携带自定义属性。ie没有在拦截器中修改HttpClient属性,只需设置一些请求属性或threadlocals,并在
CustomHttpClient
类方法中处理这些自定义设置。Spring容器中通过XML或注释支持声明的所有bean默认为单例。如果将作用域设置为prototype的bean注入到单例(例如控制器)中,它将只注入一次。有一种方法可以实现这一目标。这就是您应该如何声明范围为原型的bean。这意味着每次从容器调用这个bean时,容器都会给您一个新实例
<bean id="shoppingCart" class="example.ShoppingCart" scope="request">
<aop:scoped-proxy />
</bean>
我可能错了,但我认为如果您需要为这个原型可重用组件进行注入,则设计可能存在缺陷,您需要根据请求修改其属性。如果您手动控制创建和销毁,可能是最好的。毕竟,并不是所有的对象都应该被注入。嗯,这可能是一个很好的观点。但是如果我不自动连线并注入组件,我还能用拦截器调整它的属性吗?假设我无法控制使用该组件的实际服务,只能通过HTTP头和/或查询字符串参数调整某些属性。这就是我使用自动连线的主要原因。如果您只需要调整标题和/或参数,为什么不修改HttpServletRequest
/HttpServletResponse
?这就是为什么它们可以在拦截器中使用的原因。修改请求将是理想的,但我认为如果不先自动连接,就无法进入CustomHttpClient的请求范围。如果我将新的头设置为HttpServletRequest对象,那么它就是这样做的,但是我需要对底层组件进行更多的处理,因为CustomHttpClient所在的位置。@isyndicate我已经为您提供了答案。请在审阅后提供一些反馈。让我知道这是否对您有效。ThreadLocal
似乎是解决此问题的一种非常严厉的方法。如果您要使用线程局部变量,您必须确保取消设置它们(我指的是必须非常小心并考虑使用finally块)。@Aurand Ya您需要确保取消设置线程局部变量的值,这可以通过创建一个自定义的会话保持器来轻松确保,该会话保持器可以在进入和退出时调用。但这在易访问性方面提供了优势。正如我在问题中提到的,我尝试使用prototype scope,但这与通过拦截器自动连接和注入属性的目的背道而驰。因为,作为一个原型,每次都会创建一个新的实例,因此不会对拦截器进行任何更改。