Need some help with Spring autowiring, and scopes.
Here is the basic app structure:
I have an CustomHttpClient, annotated as @Component, and also pulling some config-related properties from application.properties file (via @Value annotation).
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;
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);
...
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:
I tried changing the scope of CustomHttpClient to @Scope("prototype"), but that way I can no longer change settings of CustomHttpClient with an interceptor.
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.
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.
If your interceptor is only addding some properties then using thread local should be a better option. You can call ThreadLocal.set(custom Map) and use it wherever you want for the running thread and when your program is going to leave your controller you can call ThreadLocal.Unset which will clear the value stored.
This way you wont need a new instance of HttpcLient everytime, also a new instance every time would be a serious flaw. And you will be able to use your custom map anywhere you want in the running thread.
All beans declared in the Spring container enther by XML or by annotation support are by default singletons. If you inject a bean with scope set to prototype into a singleton e.g. a controller it will inject it only once. There is a way to achieve this goal. This is how you should declare a bean scoped as a prototype. This means that the container will always give you a new instance each time this bean is called upon from the container.
<bean id="shoppingCart" class="example.ShoppingCart" scope="request">
<aop:scoped-proxy />
</bean>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With