我们将Spring bean实现为单例(默认)。此bean用作Web服务的一部分,并且在触发多个同时请求时,响应持有者(单例bean)在尝试检索时抛出NullPointerException。这通常在构建响应时发生,然后在发送原始响应之前触发新请求。
这可能是由于Bean的Singletion实现吗?如果是的话,是不会改变原型来解决我的问题。如何使用新操作员始终启动它?这样做会对性能产生任何影响吗?或者有更好的方法。
非常感谢任何帮助。
修改:
代码详情
public class BuildToolRequestProcessor {
private BuildToolResponse buildToolResponse;
.....
//And it has been referenced in the code in different methods, setting the response details..
public String process(BuildToolRequestXml buildToolRequestXml) throws Exception {
buildToolResponse.setLocation(location);
...
public String handleDetails(BuildToolRequestXml buildToolRequestXml) throws Exception {
buildToolResponse.setSchedule(schedule);
...
// And in another method, when I try to retrieve the Location, it throws a Null Pointer Exception..
buildToolResponse.getLocation().getPinCode()
//Bean configuration
<bean id="buildToolResponse"
class="com.raj.buildTool.processor.BuildToolResponse"/>
附加说明:我尝试在延迟第一个请求的响应之前引入延迟,然后发出另一个请求。第二个请求将Location重置为NULL,因此在尝试检索Location时会抛出NPE。这可能是因为单身人士吗?此外,我还没有使用new运算符再次初始化buildToolResponse,但BuildToolResponse类扩展自BuildToolResponseBuilder,我使用'new'初始化来构建响应。
答案 0 :(得分:1)
这可能是由于Bean的Singletion实现吗?如果是的话,是否有可能改变原型来解决我的问题。
如果你有一个单独的bean,请确保这个bean 不维持任何状态。这意味着,它不应该有任何基于某些方法重新初始化的字段,除了注入由Spring完成的另一个bean或资源。这可能会导致并发问题,特别是在多个线程中使用bean时(在这种情况下,要参加对Web服务执行的多个请求)。
这是一个将在多个线程上使用的Spring bean的错误设计示例:
@Component
public class SingletonByDefaultBean {
private StringBuilder responseBuilder;
@Autowired
private FooService fooService;
public String methodUsedInSeveralThreads() {
//here you will have a concurrency issue
responseBuilder = new StringBuilder();
//write contents into the response
//...
//return the response
return responseBuilder.toString();
}
}
要解决此问题,您有两种方法:
删除bean的任何状态并将属性移动到方法局部变量中:
@Component
public class SingletonByDefaultBean {
//private StringBuilder responseBuilder;
@Autowired
private FooService fooService;
public String methodUsedInSeveralThreads() {
StringBuilder responseBuilder = new StringBuilder();
//write contents into the response
//...
//return the response
return responseBuilder.toString();
}
}
将bean的范围更改为原型
@Component
@Scope("prototype")
public class SingletonByDefaultBean {
private StringBuilder responseBuilder;
@Autowired
private FooService fooService;
public String methodUsedInSeveralThreads() {
responseBuilder = new StringBuilder();
//write contents into the response
//...
//return the response
return responseBuilder.toString();
}
}
如何使用new运算符始终启动它?
请参阅this answer以了解如何手动创建类的实例并使它们由Spring管理。这并不容易,我建议只有在你真正理解你正在做的事情时才使用这些方法。