Java 在Spring中创建新实例和使用范围原型注释的区别
我的应用程序正在侦听交换(使用Java 在Spring中创建新实例和使用范围原型注释的区别,java,spring,spring-mvc,annotations,rx-java2,Java,Spring,Spring Mvc,Annotations,Rx Java2,我的应用程序正在侦听交换(使用rabbitMQ),希望接收一些API数据,然后将其重定向到相关位置 我正在使用rxJava订阅这些更改,目的是打开一个新线程并通过每次创建RestClient发送请求->它将接收数据,解析数据,发送数据,然后将响应发送回队列 我的问题是,我希望每次都创建一个RestClient的新实例。考虑使用Springs范围注释:@Scope(value=ConfigurableBeanFactory.Scope\u PROTOTYPE)但似乎无法理解如何使用它,以及如果每次
rabbitMQ
),希望接收一些API数据,然后将其重定向到相关位置
我正在使用rxJava
订阅这些更改,目的是打开一个新线程并通过每次创建RestClient
发送请求->它将接收数据,解析数据,发送数据,然后将响应发送回队列
我的问题是,我希望每次都创建一个RestClient的新实例。考虑使用Springs范围注释:@Scope(value=ConfigurableBeanFactory.Scope\u PROTOTYPE)
但似乎无法理解如何使用它,以及如果每次使用新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();
}
类MyManager{
@自动连线
私有WebApplicationContext上下文;
....
...
...
@施工后
myListener.subscribeOn(Schedulers.computation()).subscribe(this::handleApiRequest);
私有void handleApiRequest(ApiData ApiData){
//备选案文1:
RestClient=newrestclient();
客户端.handleApiRequest(apiData);
//备选案文2:
//使用原型?
RestClient x=(RestClient)context.getBean(“restTest”)。。
}
}
@服务
//@范围(值=ConfigurableBeanFactory.Scope\u PROTOTYPE)//需要??
类RestClient{
私有字符串服务器;
私人休息;
私有HttpHeader;
反应性反应性;
@施工后
私有void updateHeaders(){
headers.add(Utils.CONTENT\u TYPE,Utils.APPLICATION\u JSON);
headers.add(Utils.ACCEPT,Utils.PREFIX\u ALL);
}
公共无效HandLeapRequest(ApiData apiRequest){
sendRequest(apiRequest);//已实现
sendResponse();//已实现
}
}
@Bean(name=“restest”)
@范围(“原型”)
公共RestClient getRestTemplate(){
返回新的RestClient();
}
当您使用context.getBean
时,返回的实例是Springbean,Spring处理依赖项注入、配置、生命周期回调。当您仅使用new
创建它时,这些都不会发生。在您给出的示例中,@PostConstruct
方法仅在您使用context.getBean
时才会被调用。当您使用context.getBean()返回的任何bean时,该bean的生命周期将由Spring处理
但若您使用新实例初始化bean,那个么您将负责对象的创建及其生命周期。(因此该类中的@PostConstruct和其他spring注释将毫无意义。)该bean中的任何依赖项都不会被注入 首先,resttemplate是。不要根据请求或使用new关键字(构造函数)实例化它,这是一个糟糕的设计。因为您在这里注释掉了
@Scope(value=ConfigurableBeanFactory.Scope\u PROTOTYPE)
;默认情况下,spring将创建一个RestClient
的单例bean,无论您在哪里自动连接,您都将获得相同的RestClient
实例;所以你做得对
@Service
//@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //NEEDED??
class RestClient {
不过我这里有一个问题,在RestClient中,您在哪里实例化私有rest模板rest代码>我在你发布的代码中没有看到这一点
如果您按照建议从prototype范围移动到singleton范围,您可以使用@Autowired RestClient-RestClient代码>
而不是
@Autowired private WebApplicationContext context;
RestClient x = (RestClient)context.getBean("restTest")
少用样板。谢谢!我读了更多关于它的内容,删除了原型并自动连接RestClient抱歉,是吗:)非常有用