Spring用到了哪些设计模式?

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
简介: Spring用到了哪些设计模式?

Spring 作为企业级应用开发中最受欢迎的框架之一,其内部广泛采用了多种设计模式,使得框架不仅功能强大,而且具有很高的可扩展性和灵活性。是我们学习设计模式不可多得的优质材料。

一 单例模式 (Singleton Pattern)

在 Spring 框架中,单例模式被广泛应用于各种组件和工具类,以确保在整个应用程序生命周期中,这些对象只有一个实例,从而节省内存和提高性能。

松哥这里给大家举几个常见的 Spring 中单例的应用。

BeanFactory

BeanFactory 是 Spring 框架中的另一个核心接口,它负责创建和管理 bean。BeanFactory 的实现类(如 DefaultListableBeanFactory)也通常以单例模式存在。

源码示例:

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    @Override
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }
    @Override
    public Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    singletonObject = getEarlyBeanReference(beanName, mbd, bean);
                }
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

DefaultListableBeanFactory 本身的初始化逻辑如下:

可以看到,如果存在 BeanFactory,则先销毁,再创建新的 BeanFactory。

二 工厂模式 (Factory Pattern)

工厂模式提供了一种创建对象的接口,但让子类决定实例化哪一个类。Spring 中的 BeanFactory 接口及其实现类(如 DefaultListableBeanFactory)就是工厂模式的应用。通过这些工厂,我们可以方便地管理和创建bean实例。

Spring 源码案例

public interface BeanFactory {
    Object getBean(String name) throws BeansException;
}
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
        implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
}

DefaultListableBeanFactoryBeanFactory 的一个实现,负责创建和管理 bean 的实例。

三 原型模式 (Prototype Pattern)

原型模式通过复制现有对象来创建新对象,而无需知道任何创建细节。在 Spring 中,我们可以通过设置 bean 的 scope 属性为 prototype 来实现每次请求时都创建一个新的 bean 实例。

Spring 源码案例

<bean id="exampleBean" class="com.example.ExampleBean" scope="prototype"/>

这个配置表示每次请求 exampleBean 时,都会创建一个新的实例。

四 模板方法模式 (Template Method Pattern)

在 Spring 框架中,模板方法模式被广泛应用于多个模块,以提供灵活且可扩展的解决方案。模板方法模式的核心思想是定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。这样,子类可以不改变算法结构的情况下重新定义算法的某些特定步骤。

这里松哥和大家分享两个经典的模版方法模式:JdbcTemplate 和 PlatformTransactionManager。

JdbcTemplate

JdbcTemplate 是 Spring JDBC 模块中的一个核心类,它使用模板方法模式来简化数据库操作。

模板方法:

  • execute:执行 SQL 语句的基本方法。
  • query:查询数据库的基本方法。
  • update:执行更新操作的基本方法。

具体实现:

  • queryForObject:查询单个对象。
  • queryForList:查询列表。
  • batchUpdate:批量更新。

源码示例:

public abstract class JdbcOperations {
    public <T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException {
        return queryForObject(sql, args, getJdbcOperations().new SingleColumnRowMapper(rowMapper));
    }
    public int update(String sql, PreparedStatementSetter pss) throws DataAccessException {
        Assert.notNull(sql, "SQL must not be null");
        if (logger.isDebugEnabled()) {
            logger.debug("Executing SQL update [" + sql + "]");
        }
        Connection con = DataSourceUtils.getConnection(getDataSource());
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement(sql);
            pss.setValues(ps);
            int rows = ps.executeUpdate();
            if (logger.isDebugEnabled()) {
                logger.debug(rows + " rows affected");
            }
            return rows;
        } catch (Throwable ex) {
            // Handle exception
            throw translateException("PreparedStatement", sql, ex);
        } finally {
            JdbcUtils.closeStatement(ps);
            DataSourceUtils.releaseConnection(con, getDataSource());
        }
    }
}

PlatformTransactionManager

PlatformTransactionManager 接口定义了事务管理的基本方法,具体的事务管理实现类(如 DataSourceTransactionManager)则提供了具体的实现。

模板方法:

  • getTransaction:获取事务。
  • commit:提交事务。
  • rollback:回滚事务。

具体实现:

  • DataSourceTransactionManager:基于数据源的事务管理。
  • JtaTransactionManager:基于JTA的事务管理。

源码示例:

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
    void commit(TransactionStatus status) throws TransactionException;
    void rollback(TransactionStatus status) throws TransactionException;
}
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager {
    @Override
    protected TransactionStatus doBegin(Object transaction, TransactionDefinition definition) {
        // 获取数据库连接
        ConnectionHolder conHolder = (ConnectionHolder) transaction;
        Connection con = conHolder.getConnection();
        // 设置事务隔离级别
        Integer previousIsolationLevel = DataSourceUtils.storeIsolationLevelIfNotSet(con, definition.getIsolationLevel());
        // 开启事务
        boolean newTransaction = false;
        if (!con.getAutoCommit()) {
            logger.debug("Not switching JDBC Connection [" + con + "] to manual commit because already manually committed");
        } else {
            newTransaction = true;
            if (logger.isDebugEnabled()) {
                logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
            }
            con.setAutoCommit(false);
        }
        // 返回事务状态
        return new DataSourceTransactionObject(conHolder, previousIsolationLevel, newTransaction);
    }
}

五 适配器模式 (Adapter Pattern)

适配器模式将一个类的接口转换成客户希望的另一个接口。SpringMVC 中的 HandlerAdapter 接口及其多个实现类(如 RequestMappingHandlerAdapter)就是适配器模式的应用,它们负责处理不同类型的控制器方法。

Spring 源码案例

public interface HandlerAdapter {
    boolean supports(Object handler);
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
}
public class RequestMappingHandlerAdapter implements HandlerAdapter {
    @Override
    public boolean supports(Object handler) {
        return handler instanceof HandlerMethod;
    }
    @Override
    public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return ((HandlerMethod) handler).invokeAndHandle(request, response);
    }
}

RequestMappingHandlerAdapter 适配了 HandlerMethod 类型的控制器方法,使其能够处理HTTP请求。

六 装饰者模式 (Decorator Pattern)

装饰者模式允许动态地给一个对象添加一些额外的职责。Spring AOP 中的切面实现可以看作是对原有对象的一种装饰。通过 @Around 注解定义的环绕通知可以在不改变原有业务逻辑的情况下增加额外的功能。

Spring 源码案例

public class TransactionInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        // 开始事务
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            Object result = invocation.proceed();
            transactionManager.commit(status);
            return result;
        } catch (RuntimeException ex) {
            transactionManager.rollback(status);
            throw ex;
        }
    }
}

TransactionInterceptor 是一个典型的装饰者模式应用,它在方法调用前后添加了事务管理的逻辑。

七 观察者模式 (Observer Pattern)

观察者模式定义了对象之间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。Spring  中的 ApplicationEventApplicationListener 接口共同实现了观察者模式。

Spring 源码案例

public interface ApplicationListener<E extends ApplicationEvent> {
    void onApplicationEvent(E event);
}
public class ContextRefreshedEvent extends ApplicationEvent {
    public ContextRefreshedEvent(Object source) {
        super(source);
    }
}
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("Context refreshed!");
    }
}

MyApplicationListener 监听了 ContextRefreshedEvent 事件,当上下文刷新时,会输出一条消息。

八 代理模式 (Proxy Pattern)

代理模式为其他对象提供一个代理以控制对这个对象的访问。Spring AOP 使用动态代理技术(JDK 动态代理或 CGLIB)来实现代理模式。例如,当你在方法上添加事务管理注解 @Transactional 时,Spring 会自动创建一个代理对象来管理事务的开始和结束。

Spring 源码案例

public class DefaultAopProxyFactory implements AopProxyFactory {
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
            Class<?> targetClass = config.getTargetClass();
            if (targetClass == null) {
                throw new AopConfigException("TargetSource cannot determine target class: " +
                        "Either an interface or a target is required for proxy creation.");
            }
            return new ObjenesisCglibAopProxy(config);
        } else {
            return new JdkDynamicAopProxy(config);
        }
    }
}

DefaultAopProxyFactory 根据配置选择使用 CGLIB 或 JDK 动态代理来创建代理对象。

九 组合模式 (Composite Pattern)

组合模式允许将对象组合成树形结构以表示“部分-整体”的层次结构。在 Spring 配置中,可以将多个 bean 组合在一起形成一个复杂的结构。

Spring 源码案例

<beans>
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/testdb"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

这个配置文件中,jdbcTemplate 依赖于 dataSource,形成了一个简单的组合结构。

十 策略模式 (Strategy Pattern)

策略模式定义了一系列算法,并将每一个算法封装起来,使它们可以互换。Spring 中的 Resource 接口及其多个实现类(如 ClassPathResource, FileSystemResource)就是策略模式的应用,可以根据需要选择不同的资源访问方式。

Spring 源码案例

public interface ResourceLoader {
    Resource getResource(String location);
}
public class DefaultResourceLoader implements ResourceLoader {
    @Override
    public Resource getResource(String location) {
        if (location.startsWith("classpath:")) {
            return new ClassPathResource(location.substring("classpath:".length()));
        } else {
            return new FileSystemResource(location);
        }
    }
}

DefaultResourceLoader 根据资源路径的前缀选择合适的 Resource 实现类。

十一 小结

通过上述案例,我们可以看到 Spring 框架巧妙地运用了多种设计模式,不仅提高了代码的复用性和可维护性,还增强了框架的灵活性和扩展性。希望这篇文章能帮助大家更好地理解和掌握 Spring 中的设计模式,如果有任何疑问或建议,欢迎在评论区留言交流。

目录
相关文章
|
8天前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
11天前
|
存储 人工智能 调度
阿里云吴结生:高性能计算持续创新,响应数据+AI时代的多元化负载需求
在数字化转型的大潮中,每家公司都在积极探索如何利用数据驱动业务增长,而AI技术的快速发展更是加速了这一进程。
|
3天前
|
并行计算 前端开发 物联网
全网首发!真·从0到1!万字长文带你入门Qwen2.5-Coder——介绍、体验、本地部署及简单微调
2024年11月12日,阿里云通义大模型团队正式开源通义千问代码模型全系列,包括6款Qwen2.5-Coder模型,每个规模包含Base和Instruct两个版本。其中32B尺寸的旗舰代码模型在多项基准评测中取得开源最佳成绩,成为全球最强开源代码模型,多项关键能力超越GPT-4o。Qwen2.5-Coder具备强大、多样和实用等优点,通过持续训练,结合源代码、文本代码混合数据及合成数据,显著提升了代码生成、推理和修复等核心任务的性能。此外,该模型还支持多种编程语言,并在人类偏好对齐方面表现出色。本文为周周的奇妙编程原创,阿里云社区首发,未经同意不得转载。
|
8天前
|
人工智能 运维 双11
2024阿里云双十一云资源购买指南(纯客观,无广)
2024年双十一,阿里云推出多项重磅优惠,特别针对新迁入云的企业和初创公司提供丰厚补贴。其中,36元一年的轻量应用服务器、1.95元/小时的16核60GB A10卡以及1元购域名等产品尤为值得关注。这些产品不仅价格亲民,还提供了丰富的功能和服务,非常适合个人开发者、学生及中小企业快速上手和部署应用。
|
18天前
|
自然语言处理 数据可视化 前端开发
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
合合信息的智能文档处理“百宝箱”涵盖文档解析、向量化模型、测评工具等,解决了复杂文档解析、大模型问答幻觉、文档解析效果评估、知识库搭建、多语言文档翻译等问题。通过可视化解析工具 TextIn ParseX、向量化模型 acge-embedding 和文档解析测评工具 markdown_tester,百宝箱提升了文档处理的效率和精确度,适用于多种文档格式和语言环境,助力企业实现高效的信息管理和业务支持。
3939 3
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
|
8天前
|
算法 安全 网络安全
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
2024阿里云11.11金秋云创季活动火热进行中,活动月期间(2024年11月01日至11月30日)通过折扣、叠加优惠券等多种方式,阿里云WoSign SSL证书实现优惠价格新低,DV SSL证书220元/年起,助力中小企业轻松实现HTTPS加密,保障数据传输安全。
518 3
阿里云SSL证书双11精选,WoSign SSL国产证书优惠
|
14天前
|
安全 数据建模 网络安全
2024阿里云双11,WoSign SSL证书优惠券使用攻略
2024阿里云“11.11金秋云创季”活动主会场,阿里云用户通过完成个人或企业实名认证,可以领取不同额度的满减优惠券,叠加折扣优惠。用户购买WoSign SSL证书,如何叠加才能更加优惠呢?
989 3
|
7天前
|
数据采集 人工智能 API
Qwen2.5-Coder深夜开源炸场,Prompt编程的时代来了!
通义千问团队开源「强大」、「多样」、「实用」的 Qwen2.5-Coder 全系列,致力于持续推动 Open Code LLMs 的发展。
|
12天前
|
机器学习/深度学习 存储 人工智能
白话文讲解大模型| Attention is all you need
本文档旨在详细阐述当前主流的大模型技术架构如Transformer架构。我们将从技术概述、架构介绍到具体模型实现等多个角度进行讲解。通过本文档,我们期望为读者提供一个全面的理解,帮助大家掌握大模型的工作原理,增强与客户沟通的技术基础。本文档适合对大模型感兴趣的人员阅读。
441 18
白话文讲解大模型| Attention is all you need
|
12天前
|
存储 分布式计算 流计算
实时计算 Flash – 兼容 Flink 的新一代向量化流计算引擎
本文介绍了阿里云开源大数据团队在实时计算领域的最新成果——向量化流计算引擎Flash。文章主要内容包括:Apache Flink 成为业界流计算标准、Flash 核心技术解读、性能测试数据以及在阿里巴巴集团的落地效果。Flash 是一款完全兼容 Apache Flink 的新一代流计算引擎,通过向量化技术和 C++ 实现,大幅提升了性能和成本效益。
656 10
实时计算 Flash – 兼容 Flink 的新一代向量化流计算引擎