๐ง What is Singleton?
A Singleton ensures only one instance of a class is created and provides a global access point to it.
This is useful for:
-
Configuration classes
-
Logger objects
-
Database connection managers
-
Caching systems
๐ Problem: Thread-Unsafe Lazy Singleton
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton(); // ❌ Thread unsafe
}
return instance;
}
}
This code may create multiple instances in a multithreaded environment.
✅ Proper Thread-Safe Singleton with volatile
+ synchronized
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
⚙️ Modern Singleton Alternatives
๐น Static Holder Pattern
public class Singleton {
private Singleton() {}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
๐น Enum-based Singleton
public enum Singleton {
INSTANCE;
}
๐ฟ Singleton in Spring Framework
Spring beans are Singleton by default, meaning:
Only one instance of the bean is created per Spring container.
✅ Declaring a Singleton Bean (default)
@Component
public class AppConfig {
// default scope is Singleton
}
or explicitly:
@Component
@Scope("singleton")
public class AppConfig {
}
๐ Changing Bean Scope in Spring
You can control a bean’s scope using the @Scope
annotation.
Available Scopes in Spring (Core)
Scope | Description |
---|---|
singleton |
One shared instance per Spring context (default) |
prototype |
A new instance is created every time it's requested |
request |
One instance per HTTP request (Web only) |
session |
One instance per HTTP session (Web only) |
application |
One instance per ServletContext (Web only) |
websocket |
One instance per WebSocket session |
๐ง How to Change Bean Scope
@Component
@Scope("prototype")
public class ReportGenerator {
// A new instance is returned every time it's injected
}
Or using XML (for older Spring):
<bean id="myBean" class="com.example.MyBean" scope="prototype"/>
๐งช How to Control and Verify Scope
Example Test Class:
@SpringBootTest
public class ScopeTest {
@Autowired
private ApplicationContext context;
@Test
void testScope() {
MyBean b1 = context.getBean(MyBean.class);
MyBean b2 = context.getBean(MyBean.class);
System.out.println(b1 == b2 ? "Singleton" : "Prototype");
}
}
๐ Java 25 Best Practices for Singleton
✅ Use volatile
in lazy initialization
✅ Use @Scope("singleton")
in Spring for explicit intent
✅ Use enum
to prevent reflection/cloning
✅ Avoid heavy logic in constructor
✅ Override readResolve()
if serializing
✅ Use @ThreadSafe
for clarity
✅ Use JMH to benchmark Singleton performance
✅ Prefer DI-managed beans (Spring, Micronaut, etc.)
✅ Protect against classloader issues in plugins
๐ Conclusion
-
Use
volatile
andsynchronized
together in double-checked locking. -
Use static inner class or enum for better control.
-
In Spring, prefer letting the container manage Singleton scope.
-
Change scope using
@Scope
, depending on your app needs.
✨ Summary Table
Singleton Pattern | Thread-safe | Lazy Init | Recommended |
---|---|---|---|
static instance |
✅ | ❌ | ❌ |
synchronized method |
✅ | ✅ | ⚠️ |
volatile + sync |
✅ | ✅ | ✅ |
Static holder | ✅ | ✅ | ✅✅ |
Enum | ✅✅ | ✅ | ✅✅✅ |
Spring Singleton Bean | ✅ | ✅ | ✅✅✅ |
Would you like this exported as a Markdown file, HTML, or copy-ready for Medium/Dev.to?