我的应用正在收听交换(使用rabbitMQ
),期望接收一些API数据,然后将其重定向到相关位置。
我使用rxJava
订阅这些更改,目的是打开新主题并通过每次创建RestClient
发送请求 - >它将接收数据,解析数据,发送数据,然后将响应发送回队列。
我的问题是我希望每次都能创建一个RestClient的新实例。考虑使用Springs Scope注释:@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
但似乎无法理解如何使用它以及每次使用new RestClient
时会有什么区别。
您能否解释一下使用getBean
而不是new
?
以下是代码:
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();
}
答案 0 :(得分:2)
首先,resttemplate是thread-safe。不要根据请求或使用新关键字(构造函数)对其进行实例化,这是一个糟糕的设计。因为你在这里评论了@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
;默认情况下,spring将创建一个RestClient
的单例bean,无论你在哪里自动装备,都会获得RestClient
的相同实例;所以你做对了。
@Service
//@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //NEEDED??
class RestClient {
我在这里有一个问题,在RestClient中,你在哪里实例化private RestTemplate rest;
我在你发布的代码中没有看到它
如果您按照建议从原型范围转移到单例范围,则可以使用@Autowired RestClient restClient;
而不是
@Autowired private WebApplicationContext context;
RestClient x = (RestClient)context.getBean("restTest")
较少的样板。
答案 1 :(得分:1)
当你使用context.getBean
时,返回的实例是一个Spring bean,spring处理依赖注入,配置,生命周期回调.......当您使用new
创建它时,不会发生这种情况。在您提供的示例中,只有在使用@PostConstruct
时才会调用context.getBean
方法。
答案 2 :(得分:1)
当你使用context.getBean()返回的任何bean时,那个bean的生命周期将由Spring处理。
但是如果用新实例初始化bean,则负责创建对象及其生命周期。 (因此@PostConstruct和该类中的其他spring注释将毫无意义。)并且不会注入该bean中的任何依赖项。