Singleton实现了一个Spring bean

时间:2014-04-28 15:03:38

标签: java spring singleton prototype

我们将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'初始化来构建响应。

1 个答案:

答案 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();
    }
}

要解决此问题,您有两种方法:

  1. 删除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();
        }
    }
    
  2. 将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();
        }
    }
    
  3.   

    如何使用new运算符始终启动它?

    请参阅this answer以了解如何手动创建类的实例并使它们由Spring管理。这并不容易,我建议只有在你真正理解你正在做的事情时才使用这些方法。