Reputation: 3392
My application is listening to an exchange (using rabbitMQ
), expecting to receive some API data and then should redirect it to the relevant place.
I'm using rxJava
to subscribe on these changes, when the purpose is to open a new thread and send the request by creating RestClient
each time -> it will receive the data, parse it, send it and then send the response back to queue.
My problem is that I want each time to create a new instance of my RestClient. Thought of using Springs Scope annotation : @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
but can't seem to understand how to use it and what will be the difference if I use new RestClient
each time.
Can you please explain the advantage of using getBean
over using new
?
Here is the code:
class MyManager {
@Autowired
private WebApplicationContext context;
....
...
...
@PostConstruct
myListener.subscribeOn(Schedulers.computation()).subscribe(this::handleApiRequest);
private void handleApiRequest(ApiData apiData){
// Option 1:
RestClient client = new RestClient();
client.handleApiRequest(apiData);
//Option 2:
// use somehow the prototype?
RestClient x = (RestClient)context.getBean("restTest")..
}
}
@Service
//@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //NEEDED??
class RestClient {
private String server;
private RestTemplate rest;
private HttpHeaders headers;
ResponseEntity<String> responseEntity;
@PostConstruct
private void updateHeaders() {
headers.add(Utils.CONTENT_TYPE, Utils.APPLICATION_JSON);
headers.add(Utils.ACCEPT, Utils.PREFIX_ALL);
}
public void handleApiRequest(ApiData apiRequest) {
sendRequest(apiRequest); //implemented
sendResponse(); //implemented
}
}
@Bean(name = "restTest")
@Scope("prototype")
public RestClient getRestTemplate() {
return new RestClient();
}
Upvotes: 3
Views: 2032
Reputation: 16485
First of all, resttemplate is thread-safe. Don't instantiate it per request or using new keyword (Constructor), that is a bad design. Because you commented out @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
here; and by default, spring will create a singleton bean of RestClient
and you will get the same instance of RestClient
wherever you autowire; so you are doing it right.
@Service
//@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //NEEDED??
class RestClient {
I have a question here though, in RestClient, where are you instantiating private RestTemplate rest;
I am not seeing that in the code that you posted
And if you are moving to singleton scope from prototype scope as suggested, you can use @Autowired RestClient restClient;
instead of
@Autowired private WebApplicationContext context;
RestClient x = (RestClient)context.getBean("restTest")
Less boilerplate.
Upvotes: 3
Reputation: 2456
When you use any bean returned by context.getBean(), then lifecycle of that bean will be handled by Spring.
But if you initialise bean with new instance, you are responsible for object creation and it's life cycle. (And hence @PostConstruct and other spring annotations inside that class will be meaningless.) And any dependencies inside that bean will not be injected.
Upvotes: 1
Reputation: 6314
When you use context.getBean
the returned instance is a Spring bean, spring handles dependency injection, configuration, lifecycle callbacks... . When you just create it using new
none of that happens. In the example you gave the @PostConstruct
method is going to be called only if you use context.getBean
.
Upvotes: 1