1

I am learning Spring and have found the book Spring in Practice to be an awesome source. I don't understand Spring bean singleton scopes completely however. And what I read in the section of bean scopes has confused me a bit.

Here is a excerpt from that section:

As you request singleton beans from the container, Spring will create instances and cache them if they haven’t been created; otherwise, Spring will return already-existing instances from its cache. Therefore, singleton beans in Spring often don’t maintain state because they’re usually shared among multiple threads (such as in servlet environments). For example, singleton services often have references to singleton DAOs, and the DAOs might have references to Hibernate SessionFactorys, which are threadsafe.

Now I don't know much about multithreading in Java so please pardon my ignorance. In the above excerpt where it says "Therefore, singleton beans in Spring often don’t maintain state because they’re usually shared among multiple threads"

1). What does this mean for domain objects? Can I have a domain object called User defined as a singleton scope in the spring context? What would happen?

2). I notice that mostly datasources and large configurations are usually in the spring xml file. I have a feeling my questions relating to state and beans defaulting to singletons is related to wiring only big parts of an application.

Can someone clarify this topic for me? An example would be really helpful.

Thank you in advance.

Horse Voice
  • 8,138
  • 15
  • 69
  • 120

2 Answers2

2

A Java class is a description of state and behavior. An instance of that class is a holder of state that can exhibit behavior. Therefore, this class

public class Foo {
    private String bar;
    public Foo(String bar) {this.bar = bar;}
    public void print() {System.out.println(bar);}
    public void setBar(String bar) {this.bar = bar;}
}

describes a data structure which has a String as state and print() and setBar(String) methods as behavior. If you create an instance

new Foo("the state");

You now have an actual data structure that holds the String data (or state) "the state" and that can display that data by invoking the print() method or change it with setBar(String).

The problem with the class above is that it is mutable, ie. its state can change. If multiple threads are operating on it, you might see unexpected behavior. For example, one thread changes bar's value before another thread has the chance to print() out its previous value.

What does this mean for domain objects? Can I have a domain object called User defined as a singleton scope in the spring context? What would happen?

This means the exact same thing for domain objects as it does for service or presentation objects. You can very much have a domain object of type User defined as singleton scope in the Spring context. If you want to is a different question. Do you want your application to only ever have access to that one User instance? No, then don't make it singleton. Yes, then make it singleton. This only applies if Spring is actually managing the instances for you.

More clarifications:

It's important to understand what a Singleton is. Wikipedia says

restricts the Instantiation of a class to one object

If we are taking about restricted in regards to a JVM, a Singleton could be implemented as described here. If we are talking about restricted in regards to a Spring ApplicationContext, then we are talking about a Spring managed singleton scope bean (read the chapter carefully). For example

<bean id="customBean" class="org.mine.CustomBean" />

which is retrieved like

(CustomBean) context.getBean("customBean");
// or
context.getBean(CustomBean.class);

If we are always retrieving the instance from Spring's ApplicationContext, we are effectively only ever instantiating the class once.

So if that variable is being accessed by different parts of the application, the state of the object can be changed by that variable by executing for instance the setter methods on that variable. But that seems like a singleton to me.

A web application is multi-threaded. If each thread is accessing the singleton bean and mutating it, you might get lost updates. These are typically not desired since you cannot predict them and therefore are hard to test.

That variable can be used to keep changing the same data structure throughout different parts of the application. So how is the Foo object not a singleton?

As stated earlier, Singleton is a pattern that describes how an instance is unique in regards to some context. Simply doing

new Foo("the state");

doesn't make that object a singleton. It's how you use it that makes it a singleton.

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • So in the above example you showed, you have a new `Foo` object created. So it will be assigned to a variable correct. So if that variable is being accessed by different parts of the application, the state of the object can be changed by that variable by executing for instance the setter methods on that variable. But that seems like a singleton to me. That variable can be used to keep changing the same data structure throughout different parts of the application. So how is the Foo object not a singleton? – Horse Voice Dec 03 '13 at 19:37
  • @TazMan A singleton depends on how you use it. If we are talking about Spring's singleton scope, you are letting Spring manage the instance which it returns for any request for an object of its type. Typically, you don't want a singleton to have mutable state. – Sotirios Delimanolis Dec 03 '13 at 19:58
  • I don't think you read my entire question in the comment. Could you please elaborate? – Horse Voice Dec 03 '13 at 23:19
  • @TazMan I've edited my answer to try and provide more details. Let me know if something still isn't clear. – Sotirios Delimanolis Dec 03 '13 at 23:41
2

Well, if multiple threads change the same object at the same time, they'll interfere with each other. Most spring applications harness the power of multiple threads.

A singleton scoped bean corresponds to a single object (hence the name). Everyone asking for that bean will get the same object.

Therefore, you should not change that shared object.

What does this mean for domain objects? Can I have a domain object called User defined as a singleton scope in the spring context? What would happen?

Sure you could declare a bean of type user, but - as we learned above - everyone asking for that bean will get the same user object. Is this really what you want? For instance, if the bean is intended to represent the logged in user, this design would imply that only a single user can log in ...

On the other hand, if the bean merely holds configuration data that equally applies to all users, it would be quite reasonable to for the threads to share the same object (of course, if they change it, synchronization is required to prevent interference).

I notice that mostly datasources and large configurations are usually in the spring xml file.

That is indeed the typical use. Data that should be different for each thread is typically kept in local variables (or objects reachable from there). Because local variables are different for each method invocation, interference by other threads is not possible.

You can also use spring to manage short lived objects by declaring beans with a short-lived scope (such as session or request scope in a servlet environment) - though in that case, you'll have to take care that different threads don't access the state of the same object at the same time. With request scope, that's usually easy because requests are usually processed by a single thread. With session scope, you'll actually have to synchronize access.

meriton
  • 68,356
  • 14
  • 108
  • 175