什么是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 的 BeanFactory 和 ApplicationContext 是典型的 工厂模式应用(更准确地说,是简单工厂的变体)。

不直接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() 发布事件,多个监听器可以异步或同步响应,实现模块解耦。比如用户注册后触发邮件发送、积分增加等操作。

相关推荐
蛋蛋的就会顺顺的7 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
需要8268 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
小 黄 鸡8 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
伯恩bourne10 小时前
Spring Boot Bean 注册的两种方式:@Component 家族 vs @Configuration + @Bean
java·spring boot·后端
silvamux_10 小时前
curl 测试 OpenAI 兼容 API 的完整流程
java·人工智能·缓存·ai·oneapi
省钱兄--zs10 小时前
深圳24小时自助健身房软硬件解决方案实战指南与开发流程详解
java·数据仓库·spring boot·小程序·架构
顽疲11 小时前
Java vue 养老系统源码详解:月账单 care_month_bill 与 Quartz 扣费 Job 实践
java·开发语言·vue.js·vue养老·springboot养老·java养老
Wang's Blog11 小时前
Java 项目实战: 交友项目 - 安装开发工具与环境准备
java·开发语言·交友
用户212968352616811 小时前
开源了一个 Java 多智能体 LLM 框架 Baton:一个依赖,把 Agent 循环、工具调用、记忆、编排全配齐
java·llm
helmsail11 小时前
05 管理活动与选品
java