编程中的智慧六:单例、原型、建造者

上一篇咱们结合Spring介绍了设计模式中的工厂模式相关方法,其实现在Java开发基本上都是基于Spring框架开发,所以后续我们在开发过程中基本上很少自己重写一个工厂模式,都是直接使用Spring来完成。今天咱们接着看剩下的创建型设计模式:单例、原型、建造者。

单例模式在Spring中的应用详解

单例模式确保一个类只有一个实例,并提供一个全局访问点。Spring框架默认情况下对所有Bean使用单例模式,即一个Bean只会被创建一次,并在整个Spring容器中共享。

1. 单例模式概述

单例模式包含以下角色:

  • 单例类:定义一个私有的构造函数,确保只能通过静态方法获取唯一实例。
  • 静态方法:提供获取单例实例的全局访问点。
2. 单例模式在Spring中的实现

源码分析:之前Spring源码相关内容已经分析过了这边直接贴代码来

Spring中的DefaultSingletonBeanRegistry类实现了单例模式。该类维护了一个缓存,用于存储单例Bean实例。

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);@Overridepublic Object getSingleton(String beanName) {return this.singletonObjects.get(beanName);}protected void addSingleton(String beanName, Object singletonObject) {this.singletonObjects.put(beanName, singletonObject);}
}

在Spring容器初始化过程中,当一个Bean被创建时,如果其作用域为单例(默认情况),Spring会调用addSingleton方法将该Bean实例放入singletonObjects缓存中。在以后每次请求该Bean时,Spring会从缓存中直接返回该实例,而不再创建新的实例。

原型模式在Spring中的应用详解

原型模式通过克隆现有的对象来创建新对象。Spring支持原型作用域(prototype),每次请求一个原型作用域的Bean时,都会创建一个新的实例。

1. 原型模式概述

原型模式包含以下角色:

  • 原型接口:定义一个克隆方法。
  • 具体原型类:实现克隆方法,返回自身的一个副本。
2. 原型模式在Spring中的实现

源码分析:

在Spring中,通过配置Bean的作用域为prototype来实现原型模式。在DefaultListableBeanFactory中,处理原型作用域的代码如下:

// 如果是原型beanelse if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {// 实例化前置准备工作beforePrototypeCreation(beanName);// 开始实例化prototypeInstance = createBean(beanName, mbd, args);}finally {// 实例化以后的处理工作afterPrototypeCreation(beanName);}// 获取原型bean实例对象bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}

 这里可以明显的看到如果是原型模式,Spring会直接调用createBean而不会从单例缓存池中获取。

构建者模式在Spring中的应用详解

构建者模式通过逐步构建复杂对象,允许创建者一步步构建其表示。Spring中的BeanDefinitionBuilder类使用了构建者模式,用于动态创建Bean定义。

1. 构建者模式概述

构建者模式包含以下角色:

  • 构建者:提供构建复杂对象的各个方法。
  • 具体构建者:实现构建者接口,构建具体的复杂对象。
  • 指导者:指导构建者如何构建复杂对象。
  • 产品:最终构建的复杂对象。
2. 构建者模式在Spring中的实现

源码分析:

Spring中的BeanDefinitionBuilder类使用了构建者模式:

public class BeanDefinitionBuilder {private AbstractBeanDefinition beanDefinition;private BeanDefinitionBuilder(Class<?> beanClass) {this.beanDefinition = new GenericBeanDefinition();this.beanDefinition.setBeanClass(beanClass);}public static BeanDefinitionBuilder genericBeanDefinition(Class<?> beanClass) {return new BeanDefinitionBuilder(beanClass);}public BeanDefinitionBuilder addPropertyValue(String name, Object value) {this.beanDefinition.getPropertyValues().add(name, value);return this;}public AbstractBeanDefinition getBeanDefinition() {return this.beanDefinition;}
}

使用BeanDefinitionBuilder时,可以通过链式调用逐步设置Bean的各个属性,最终调用getBeanDefinition方法获取构建的Bean定义。例如:

BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyBean.class);
builder.addPropertyValue("name", "testName").addPropertyValue("age", 30);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();

通过上述详细分析,我们可以看到Spring框架在其设计和实现中广泛应用了单例模式、原型模式和构建者模式。这些设计模式不仅提高了代码的可维护性和可扩展性,还使得Spring框架能够灵活地管理对象的创建和依赖注入。

当然实际生产中,我们业务处理的类基本上都是交给Spring管理的如Service、Controller、Mapper等,这些类默认情况下都是单例,当我指定作用域为Prototype的时候,其实就是走了不同的判断逻辑,然后每次都需要重新创建。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/48623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Dubbo学习笔记

Dubbo 简介 Apache Dubbo是一款高性能的Java RPC框架。其前身是阿里巴巴公司开源的一个高性能、轻量级的开源Java RPC框架&#xff0c;可以和Spring框架无缝集成。 其中文官网:https://dubbo.gitbooks.io/dubbo-user-book/content/ 特性和用法 架构 节点角色说明 节点角色…

应用层的重点协议

目录 一、DNS 二、NAT 1、技术背景 2、NAT机制IP转化过程 三、NAPT NAT技术的缺陷 四、HTTP 1、协议格式 2、HTTP请求 1&#xff09;method(方法) GET请求的特点 POST请求的特点 GET和POST的区别 2&#xff09;URL(网址) 基本格式 关于URL encode 3&#xff0…

el-table表头使用el-dropdown出现两个下拉框

问题描述&#xff1a;el-table在固定右边列时&#xff0c;表头使用el-dropdown会出现两个下拉框&#xff0c;如图所示&#xff1a; 解决方法&#xff1a; 1.只显示第一个下拉框&#xff0c;通过控制样式将其他的下拉框display:none; 2.如图所示&#xff0c;修改插槽写法&…

<数据集>学生课堂行为识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;13899张 标注数量(xml文件个数)&#xff1a;13899 标注数量(txt文件个数)&#xff1a;13899 标注类别数&#xff1a;8 标注类别名称&#xff1a;[js, tt, dk, zt, dx, zl, jz, xt] # 举手 js # 抬头听课 …

从FasterTransformer源码解读开始了解大模型(2.3)代码通读04

从FasterTransformer源码解读开始了解大模型&#xff08;2.3&#xff09;代码解读04-forward函数 写在前面的话 本篇的内容继续解读forward函数&#xff0c;从972行开始进行解读 零、embedding函数 让我们考虑一种不包含prefix_soft_prompt的情况&#xff0c;从999行的embe…

在 PostgreSQL 里如何实现数据的冷热数据分层存储的自动化策略调整?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 在 PostgreSQL 里如何实现数据的冷热数据分层存储的自动化策略调整 在 PostgreSQL 里如何实现数据的冷…

【数据分享】2013-2022年我国省市县三级的逐日SO2数据(excel\shp格式\免费获取)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000——2022年的省市县三级的逐日PM2.5数据和2013-2022年的省市县三级的逐日CO数据&#xff08;均可查看之前的文章获悉详情&#xff09;&#xff01; 本次我们分享的是我国2013——2022年的省…

mongodb数据导出与导入

一、先去检查mongodump mongodump --version 如果报 mongodump version: built-without-version-string 或者其他的较老的版本&#xff0c;直接去下载最新的【传送门】 【以Ubuntu18.04为例】 安装工具 假设你下载的是 .tgz 文件&#xff08;适用于 Linux 系统&#xff09;&am…

【项目】星辰博客介绍

目录 一、项目背景 二、项目功能 1. 登录功能&#xff1a; 2. 列表页面&#xff1a; 3. 详情页面&#xff1a; 4. 写博客&#xff1a; 三、技术实现 四、功能页面展示 1. 用户登录 2. 博客列表页 3. 博客编辑更新页 4.博客发表页 5. 博客详情页 五.系统亮点 1.强…

高性能图数据库Neo4j从入门到实战

图数据库Neo4j介绍 什么是图数据库&#xff08;graph database&#xff09; 随着社交、电商、金融、零售、物联网等行业的快速发展&#xff0c;现实社会织起了了一张庞大而复杂的关系网&#xff0c;传统数据库很难处理关系运算。大数据行业需要处理的数据之间的关系随数据量呈…

【数据结构】栈和队列的深度探索,从实现到应用详解

&#x1f48e;所属专栏&#xff1a;数据结构与算法学习 &#x1f48e; 欢迎大家互三&#xff1a;2的n次方_ &#x1f341;1. 栈的介绍 栈是一种后进先出的数据结构&#xff0c;栈中的元素只能从栈顶进行插入和删除操作&#xff0c;类似于叠盘子&#xff0c;最后放上去的盘子最…

广州机房搬迁网络部署方案

新机房网络部署应包括核心模块、业务模块、光传输模块、安全模块、流量采集模块、路由模块、带外管理模块等&#xff0c;每个模块都根据业务需求规划成多个POD&#xff08;Point Of Delivery&#xff0c;基本物理设计单元&#xff09;。 核心模块部署主要实现各业务模块的高速互…

HighConcurrencyCommFramework c++通讯服务器框架 :目录,修改标题,配置,日志打印

目录规划 nginx 根目录下的三个文件 makefile :编译项目的入口&#xff0c;编译项目从这里开始 config.mk&#xff1a;也是个配置脚本用来增加变动的东西&#xff0c;应付可变 common.mk&#xff1a;最核心的编译脚本&#xff0c;每个子目录都要被编译.cpp程序 配置文件 配…

postman创建mock server

B站博主的说明&#xff1a;

《python语言程序设计》第6章2题(求一个整数各个数字的和)编写一个函数

求一个整数各个数字的和编写一个函数&#xff0c;计算一个整数各个数字的和&#xff0c; def sumDigits(n):a n // 100b n % 100 // 10c n % 100 % 10print(f"{n}数&#xff0c;分成个&#xff0c;十&#xff0c;百&#xff0c;{a}{b}{c}", a b c)sumDigits(23…

算法日记day 16(二叉树的广度优先遍历|反转、对称二叉树)

一、二叉树的层序遍历 题目&#xff1a; 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3]…

SQUID - 形状条件下的基于分子片段的3D分子生成等变模型 评测

SQUID 是一个形状条件下基于片段的3D分子生成模型&#xff0c;给一个3D参考分子&#xff0c;SQUID 可以根据参考分子的形状&#xff0c;基于片段库&#xff0c;生成与参考分子形状非常相似的分子。 SQUID 模型来自于 ICLR 2023 文章&#xff08;2022年10月6日提交&#xff09;&…

vue+watermark-dom实现页面水印效果

前言 页面水印大家应该都不陌生&#xff0c;它可以用于验证数字媒体的来源和完整性&#xff0c;还可以用于版权保护和信息识别&#xff0c;这些信息可以在不影响媒体质量的情况下嵌入&#xff0c;‌并在需要时进行提取。‌本文将通过 vue 结合 watermark-dom 库&#xff0c;教大…

OpenCV 像素操作—证件照换底色详细原理 C++纯手写实现

文章目录 总体步骤1.RGB转HSV2.找出要换的底色3.取反&#xff0c;黑白颠倒4.将原图像的非背景部分复制到新背景上 完整代码1.C纯手写版2.官方API版本 总体步骤 1.RGB转HSV 为什么一定要转为HSV 颜色空间&#xff1f; 将图像从BGR颜色空间转换为HSV颜色空间是因为HSV颜色空间更…

nginx基本原理

进程模型 当nginx启动之后&#xff0c;会有一个master进程和多个worker进程。默认是一个worker进程。 master进程的作用&#xff1a;接收来自外界信号&#xff0c;向各worker进程发送信号&#xff0c;监控worker进程的运行状态&#xff0c;当worker进程在异常情况下退出后&am…