Key Design Patterns Used in the Spring Framework
This article explains how Spring employs five core design patterns—Factory, Singleton, Proxy, Observer, and Template Method—detailing their roles, code examples, and how they contribute to Spring's modular, extensible architecture.
Spring is a large enterprise framework that incorporates many classic design patterns to provide clear structure and extensibility.
1. Factory Pattern
Spring uses BeanFactory and ApplicationContext as factories to manage bean creation and lifecycle. The BeanFactory interface provides methods to obtain bean instances, while ApplicationContext extends it with additional features such as event handling and resource loading.
public interface Animal { void speak(); }
public class Dog implements Animal { public void speak() { System.out.println("Woof"); } }
public class Cat implements Animal { public void speak() { System.out.println("Meow"); } }
public class AnimalFactory {
public static Animal getAnimal(String type) {
if (type.equals("dog")) { return new Dog(); }
else if (type.equals("cat")) { return new Cat(); }
return null;
}
}
public class TestFactory {
public static void main(String[] args) {
Animal animal = AnimalFactory.getAnimal("dog");
animal.speak(); // Output: Woof
}
}2. Singleton Pattern
Spring manages beans as singletons by default; each bean has a single instance per container unless a different scope is specified. The singleton scope can also be declared explicitly with @Scope("singleton").
public class SingletonBean {
private static SingletonBean instance;
private SingletonBean() {}
public static SingletonBean getInstance() {
if (instance == null) { instance = new SingletonBean(); }
return instance;
}
public void showMessage() { System.out.println("Hello from SingletonBean"); }
}
public class TestSingleton {
public static void main(String[] args) {
SingletonBean bean = SingletonBean.getInstance();
bean.showMessage(); // Output: Hello from SingletonBean
}
}3. Proxy Pattern
Spring AOP relies on dynamic proxies to wrap target objects, enabling cross‑cutting concerns such as transaction management and logging.
public interface Service { void performAction(); }
public class ServiceImpl implements Service {
public void performAction() { System.out.println("Performing action in ServiceImpl"); }
}
public class ProxyService implements Service {
private ServiceImpl serviceImpl;
public ProxyService(ServiceImpl serviceImpl) { this.serviceImpl = serviceImpl; }
public void performAction() {
System.out.println("Proxy: Before invoking method");
serviceImpl.performAction();
System.out.println("Proxy: After invoking method");
}
}
public class TestProxy {
public static void main(String[] args) {
ServiceImpl impl = new ServiceImpl();
ProxyService proxy = new ProxyService(impl);
proxy.performAction();
}
}4. Observer Pattern
Spring’s event mechanism implements the observer pattern: an event is published and all registered listeners are notified.
public class CustomEvent extends ApplicationEvent {
private String message;
public CustomEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() { return message; }
}
@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
System.out.println("Event received: " + event.getMessage());
}
}
@Component
public class EventPublisher {
@Autowired private ApplicationContext applicationContext;
public void publishEvent(String message) {
CustomEvent event = new CustomEvent(this, message);
applicationContext.publishEvent(event);
}
}
public class TestObserver {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(CustomEventListener.class, EventPublisher.class);
context.refresh();
EventPublisher publisher = context.getBean(EventPublisher.class);
publisher.publishEvent("Hello, this is a custom event!");
}
}5. Template Method Pattern
Classes such as JdbcTemplate and JpaTemplate define a skeleton algorithm (e.g., execute()) while delegating specific steps to callbacks, embodying the template method pattern.
public abstract class AbstractTemplate {
public void templateMethod() {
stepOne();
stepTwo();
}
protected abstract void stepOne();
protected abstract void stepTwo();
}
public class ConcreteTemplate extends AbstractTemplate {
@Override protected void stepOne() {
System.out.println("Step One: ConcreteTemplate implementation");
}
@Override protected void stepTwo() {
System.out.println("Step Two: ConcreteTemplate implementation");
}
}
public class TestTemplateMethod {
public static void main(String[] args) {
AbstractTemplate template = new ConcreteTemplate();
template.templateMethod();
}
}In summary, Spring leverages the factory, singleton, proxy, observer, and template method patterns to achieve loose coupling, modularity, and maintainable code, enabling developers to build enterprise applications efficiently.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
java1234
Former senior programmer at a Fortune Global 500 company, dedicated to sharing Java expertise. Visit Feng's site: Java Knowledge Sharing, www.java1234.com
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
