Sumeet Kumar Yadav
Sumeet Kumar Yadav

Reputation: 12945

Spring Singleton behavior in a multi-threaded environment

I am new to spring. On reading the documentation I found it's mentioned that

Bean default scope is a singleton.

If it has only a single instance in the container then "How it behaves in the multi-threaded environment ".

Typically in any web application, multiple requests will be done at the same time and if a POJO class is autowired and multiple requests are done at the same time then getter and setter will be crossing data of each other. Request 1 sets the data and same time request 2 override. Request 1 gets overridden data of request 2.

Like Foo is a POJO class whose get and set is not synchronized.

 @Service
    public class Foo {
        String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

   

     @Autowired
        private Foo foo;
    
        @RequestMapping(value = "foo" , method = RequestMethod.POST )
        public String saveFoo(@RequestBody String fooname){
            foo.setName(fooname);  // In case of multiple request 
                                  //get and set will be happing on same instance could be wrong
            return foo.getName();
        }

What is the ideal way to handle Autowire and POJO in a multi-threaded environment? Does the developer had to mention the prototype scope ?

Upvotes: 2

Views: 2032

Answers (4)

Mohit Sharma
Mohit Sharma

Reputation: 380

  • If a class hold any state. Then it is a candidate for @Autowired Prototype Bean. At each request a new bean should be created. Hence it will provide you the desired functionality. e.g. POJO, Entity, DTO's

  • If a class is for Utility/Behavior and doesn't hold any state than mark it as @Autowired default Singleton bean. e.g. Services, Gateways, Controllers.

  • If a class contains state, but you don't need any Spring functionality in that class. Use new keyword to create that object/ or Some Factory.. @Autowired is for Spring managed beans. e.g. Entity, POJO's

  • If a class contains both state and behavior methods. Use SLP ( Single Responsibility Principle and move it to separate classes )

Furthermore:

  1. Spring use servlet threads internally , All Spring managed beans are thread safe ( i.e Classes created by Spring framework)
  2. Its your responsibility to carefully use Spring beans.
  3. Injection of beans is tricky, i.e A Singleton Bean Injected in Prototype Bean.

Upvotes: 1

hooknc
hooknc

Reputation: 4991

If your @Service must store state, I would recommend looking into the Command Pattern.

The command could be created from a Factory, which hopefully would be thread safe and provided to the classes that need it via 'prototype' scope.

If you wanted to get really fancy you could look into CQRS (Command Query Responsibility Segregation). CQRS won't help you with your threading, but it does change the execution timing of commands.

Upvotes: 0

In general, service objects should be stateless. Your problem is that you are storing data directly in your Foo, which is not where it belongs. Calls to services should include all of the necessary parameters in the method signature; persistent objects should be saved somewhere (like a database) and referred to by key (perhaps kept in an HTTP session or sent as a request parameter).

Upvotes: 3

Amimul Ehsan Rahi
Amimul Ehsan Rahi

Reputation: 604

Spring beans are not thread-safe.......It's your responsibility to provide thread-safety.

Refer to this for best practices:

Spring bean thread safety

Upvotes: 1

Related Questions