什么是Spring设计模式:单例、工厂与代理

设计模式

单例模式(singleton)

Spring默认将Bean创建为单例,避免重复创建对象带来的性能开销

  • 目的:确保一个类只有一个实例,并且提供一个全局访问点

  • 应用场景:数据库连接池、日志记录器、配置管理器

    java 复制代码
    @Component
    public class MyService{
    	//默认是单例
    }
    //如果要修改作用域,可以用`@Scope("prototype")`

    一般在面试中可能会问手撕单例模式,一般面试最希望的成品是:

    java 复制代码
    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;
    	}
    }
    1. 一定要加volatile保证可见性+禁止指令重排序,因为instance = new Singleton();并非一个原子操作,会经历3步,其他线程可能还没等对象初始化完,就操作了

    2. DCL需要Double-check:

      1. 第一次检查(无锁):提高性能。如果实例已经创建,直接返回,避免每次都加锁。
      2. 第二次检查(有锁):保证线程安全。防止多个线程同时通过第一次检查后,都进入 synchronized 块并各自 new 一个实例。

      总结:"DCL 中的两次 null 检查各有作用:

      • 第一次检查在同步块外,是为了避免每次调用都加锁,提升性能;
      • 第二次检查在 synchronized 块内,是为了防止多个线程同时通过第一次检查后,重复创建实例。

      同时,instance 字段必须用 volatile 修饰,禁止指令重排序,确保其他线程不会拿到一个尚未完全初始化的对象。"

    Spring单例!=JVM单例:Spring单例是容器级单例(每个ApplicationContext一个实例),不是JVM全局单例、如果有两个ApplicationContext那么就有两个MyService

工厂方法模式(Factory Method)

Spring 的 BeanFactoryApplicationContext 是典型的 工厂模式应用(更准确地说,是简单工厂的变体)。

不直接new对象,而是通过工厂来获取

  • 目的:定义一个创建对象的接口,但让子类决定序列化哪一个类

  • 应用场景:日志记录器、不同数据库驱动的创建

    java 复制代码
    ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    MyService service = context.getBean(MyService.class); 
    // 工厂方法

    Spring IOC容器本质就是一个工厂,负责创建管理Bean不需要手动new,通过getBean()或依赖注入来获取,实现创建域使用的解耦

代理模式(Proxy Pattern)

实现AOP

通过代理对象,在不修改原类的情况下增强功能

java 复制代码
@Service
public class UserService {
    @Transactional // Spring 会为这个方法生成代理,加入事务控制
    public void saveUser() { ... }
}

Spring会根据情况选择:

  • JDK动态代理(基于接口)
  • CGLIB代理(基于子类)

补充说明:

如果目标类实现了接口 → 默认使用 JDK 动态代理

如果目标类没有实现接口 → 使用 CGLIB 代理 (可通过配置强制使用 CGLIB)

(观察者模式)------事件驱动

虽然有时被误称为'生产-消费',但 Spring 的事件机制本质上是 观察者模式,而非基于队列的生产-消费者模型。

在Spring中更准确地体现为事件监听机制,为了实现组件间的松耦合通信

java 复制代码
// 定义事件
public class UserRegisteredEvent extends ApplicationEvent { ... }

// 发布事件
applicationContext.publishEvent(new UserRegisteredEvent(user));

// 监听事件
@Component
public class EmailListener {
    @EventListener
    public void handleUserRegistered(UserRegisteredEvent event) {
        // 发邮件
    }
}

Spring 提供了基于观察者模式的事件机制。通过 publishEvent() 发布事件,多个监听器可以异步或同步响应,实现模块解耦。比如用户注册后触发邮件发送、积分增加等操作。

相关推荐
优橙教育4 分钟前
5G网优培训 vs Java开发:转行选哪个?
java·开发语言·5g
腻害兔2 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
碎光拾影2 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
大数据新鸟3 小时前
设计模式四大基本原则
设计模式
Miao121313 小时前
微服务 API 测试实践:海外某民宿平台如何构建模式驱动测试基础设施
java·开发语言
腻害兔3 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:支付模块 yudao-module-pay,一个让产品经理都看懂的支付中台设计
java·前端·vue.js·产品经理·ai编程
CRMEB系统商城4 小时前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
keyipatience5 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
weixin_408099676 小时前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能
钱六两6 小时前
#3、SpringAI 接入deepSeek大模型(喂饭版)
java·spring boot·ai编程