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抱歉,是吗:)非常有用