Spring中使用到的设计模式及其源码分析

前言

众所周知,Spring框架是一个强大而灵活的开发框架。这不,上次的面试刚问到这些,没防住!!!因此下来总结一下。这篇文章主要介绍Spring中使用到的设计模式,自己做个面试复盘,同时希望能帮助到其他小伙伴儿们。

在这里插入图片描述

工厂模式

相信大家面试题都背过,Spring通过工厂模式来创建和管理Bean的实例。工厂模式主要定义了一个用于创建对象的接口,让子类决定实例化哪一个类。在Spring中,BeanFactoryApplicationContext接口是实现工厂模式的关键。

那么什么是BeanFactoryApplicationContext呢???👇👇👇

BeanFactory是Spring中最底层的容器接口,它提供了基础的依赖注入功能。ApplicationContext扩展了BeanFactory,并添加了更多高级功能,比如国际化、事件传播、资源加载等(这个也是面试重点!!!)。

我们以ApplicationContext为例,它提供了getBean(String name)方法来获取Bean实例。当调用这个方法的时候,ApplicationContext会根据配置信息创建或获取Bean实例。

	ApplicationContext context = new ClassPathXmlApplicationContext("springDemo.xml");  MyBean myBean = context.getBean("myBean", MyBean.class);

AbstractApplicationContextgetBean方法通过调用getBeanFactory().getBean()来实际获取Bean实例。而BeanFactory的实现类(比如DefaultListableBeanFactory)负责根据Bean的定义和依赖关系来创建和管理Bean实例。

单例模式

Spring中的Bean默认都是单例的,因此在整个Spring IoC容器中,每个Bean只会有一个实例。这是通过Bean的scope属性来进行控制的,当scopesingleton时,就表示使用单例模式。

翻阅了Spring的源码发现:👇👇👇

Spring通过DefaultSingletonBeanRegistry类中的singletonObjects(类型为ConcurrentHashMap)来管理单例Bean的实例。当请求一个Bean时,Spring会首先检查这个Map中是否已存在该Bean的实例,如果存在则直接返回,否则创建新的实例并添加到Map中。

	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);  public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {  Assert.notNull(beanName, "Bean name must not be null");  synchronized (this.singletonObjects) {  Object singletonObject = this.singletonObjects.get(beanName);  if (singletonObject == null) {  // 创建新的Bean实例singletonObject = singletonFactory.getObject();  // 添加到单例注册表中this.singletonObjects.put(beanName, singletonObject);  }  return singletonObject;  }  }

代理模式

这道题相信大家都会,面试经常被问到哈哈。Spring的AOP功能中使用了代理模式。AOP通过在目标方法执行前后添加额外的行为(比如日志、事务管理这些),而这些额外的行为是通过代理对象来实现的。Spring提供了两种代理方式:JDK动态代理和CGLIB代理。

Spring的AOP实现主要在DefaultAopProxyFactory类中。这个类负责根据配置决定使用哪种代理方式,并创建代理对象。

	if (isProxyTargetClass()) {  // 使用CGLIB代理  return createCglibProxy(beanClassLoader, beanFactory, beanClass, beanName, targetSource, interceptedMethods, proxyTargetClass);  } else {  // 使用JDK动态代理  return createJdkDynamicProxy(beanClassLoader, beanFactory, beanClass, interfaces, interceptedMethods, proxyTargetClass);  }

createJdkDynamicProxy这个方法中,Spring通过Proxy.newProxyInstance方法创建一个实现了目标对象接口的代理对象,并将所有调用转发到目标对象,同时还可以在调用前后插入额外的行为。

模板方法模式

谈论到模板方法模式,相信大家都较为熟悉。比如在前面提过的AQS中也有模板方法模式的影子。

在Spring的JdbcTemplateHibernateTemplate这些类中,都使用了模板方法模式。这些类定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现。

JdbcTemplate为例,它定义了如queryupdate等方法,这些方法包含了数据库操作的通用流程(打开连接、执行SQL、处理结果集、关闭连接等),而具体的SQL语句和参数则由调用者提供。

观察者模式

Spring的事件驱动模型使用了观察者模式。当某个事件发生时,所有注册为该事件监听器的对象都会收到通知,并且根据需要作出响应。

Spring的ApplicationEvent和ApplicationListener接口是实现观察者模式的关键。ApplicationEvent是事件对象,包含了事件的信息;ApplicationListener是监听器接口,定义了处理事件的方法。

public class CustomEvent extends ApplicationEvent {  private final 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("Received custom event - " + event.getMessage());  }  
}

在Spring的AbstractApplicationContext中,通过ApplicationEventMulticaster来管理事件的发布和监听。当事件被发布时,ApplicationEventMulticaster会通知所有注册的监听器。

策略模式

策略模式在Spring中主要用于定义一系列的算法,并将每一个算法封装起来,使它们可以互相替换。相信大家看过Spring中bean的生命周期这道面试题。Spring的BeanFactoryPostProcessorBeanPostProcessor这些接口可以被视为策略模式的应用,因为它们允许开发者在Bean的创建和初始化过程中插入自定义的逻辑。

BeanFactoryPostProcessor允许在BeanFactory标准初始化之后,修改BeanFactory的内容。这个时候我们可以实现这个接口来定义自己的策略,然后在Spring的配置文件中注册这个Bean。

Spring还有一些其他的设计模式,看到这里面试以及能防得住了,后续再介绍其他的设计模式。

本篇文章到这里就结束了,感谢各位小伙伴们的支持!

在这里插入图片描述

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

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

相关文章

Spring Security 原理

Spring Security是一个功能强大且广泛使用的身份验证和授权框架&#xff0c;专为保护Java应用程序的安全性而设计。它提供了一套可配置的安全性规则和机制&#xff0c;用于对应用程序的资源进行访问控制和保护。以下是Spring Security的主要原理&#xff1a; 1. 过滤器链&…

引领安全新风尚:WT2605/WT2003H芯片方案赋能电动汽车,打造智能低速安全报警器"

电动汽车低速报警器(AVAS)方案可采用WT2605或WT2003H方案芯片,可实现当车辆时速低于设定值(如20Km/h),报警器会发出类似发动机加速减速的声音,倒档时装置也会发出倒车警示,在嘈杂的城市环境中帮助提升行人对驶近的电动汽车的感知,降低行人、骑行者和弱势群体面临的风险。 WT26…

十分钟带你入门Go语言(Golang)开发

概述 Go语言是由 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go语言的设计目标是将静态语言的安全性和性能与动态语言的易用性相结合。Go语言在语言层面提供了对协程的支持&#xff0c;特别适合编写高并发的项目。随着使用Go语言…

基于opencv的答题卡识别

文章目录 一、背景需求二、处理步骤图片预处理检测到答题卡轮廓透视变换找每个圆圈的轮廓轮廓排序判断是否答题正确 一、背景需求 传统的手动评分方法耗时且容易出错&#xff0c;自动化评分可以可以显著提高评分过程的速度和准确性、减少人工成本。 答题卡图片处理效果如下&am…

想出国?去外企?建议网工无脑冲思科认证。

近年来&#xff0c;国内职场竞争愈发激烈&#xff0c;内卷现象严重&#xff0c;大部分人都面临着巨大的就业压力&#xff0c;或是找工作无门、或是中年危机悄然来临&#xff0c;时刻担心被职场优化。 在这样的背景下&#xff0c;出国或进入外企工作&#xff0c;成为了许多人寻…

[JavaScript] 动态获取方法参数名

JavaScript&#xff08;简称“JS”&#xff09;是一种具有函数优先的轻量级&#xff0c;解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名&#xff0c;但是它也被用到了很多非浏览器环境中&#xff0c;JavaScript基于原型编程、多范式的动态脚本语言&am…

Optional类的使用 java8(附代码)

&#x1f370; 个人主页:_小白不加班__ &#x1f35e;文章有不合理的地方请各位大佬指正。 &#x1f349;文章不定期持续更新&#xff0c;如果我的文章对你有帮助➡️ 关注&#x1f64f;&#x1f3fb; 点赞&#x1f44d; 收藏⭐️ 文章目录 一、什么是Optional&#xff1f;二、…

科研绘图系列:R语言和弦图 (Chord diagram)

介绍 和弦图(Chord Diagram)是一种用于展示多个实体之间相互关系的数据可视化方法。它通常用于表示网络或系统中不同节点(实体)之间的连接强度或流量。和弦图由一个圆形布局组成,每个节点在圆周上占据一个扇形区域,节点之间的连接通过圆内的线条(和弦)来表示。 特点:…

数据结构第七讲:栈和队列OJ题

数据结构第七讲&#xff1a;栈和队列OJ题 1.有效的括号2.用队列实现栈3.用栈实现队列4.设计循环队列 1.有效的括号 链接: OJ题目链接 typedef char StackDataType;typedef struct Stack {StackDataType* arr;//使用一个指针来指向开辟的数组int capacity;//保存数组的空间大…

springboot爱宠屋宠物商店管理系统-计算机毕业设计源码52726

目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1系统开发流程 2.2.2 用户登录流程 2.2.3 系统操作流程 2.2.4 添加信息流程 2.2.5 修改信息流程 2.2.6 删除信息流程 2.3 系统功能…

【机器学习】正规方程的简单介绍以及如何使用Scikit-Learn实现基于正规方程的闭式解线性回归

引言 Scikit-learn 是一个开源的机器学习库&#xff0c;它支持 Python 编程语言。它提供了多种机器学习算法的实现&#xff0c;并用于数据挖掘和数据分析 文章目录 引言一、正规方程的定义二、正规方程的原理三、使用 Scikit-Learn 实现基于正规方程的闭式解线性回归3.1 工具3.…

实验15.多线程调度

简介 实验.多线程调度 内核线程 1.在时钟中断函数中处理中&#xff0c;减少当前线程pcb的tick&#xff0c;tick为0则启动调度2.调度&#xff0c;把当前线程pcb放入就绪对立队尾&#xff0c;把就绪线程队首拿出来执行主要代码 引导 省略内核 list.h #ifndef __LIB_KERNEL_…

【2024最新】 服务器安装Ubuntu20.04 (安装教程、常用命令、故障排查)持续更新中.....

安装教程&#xff08;系统、NVIDIA驱动、CUDA、CUDNN、Pytorch、Timeshift、ToDesk、花生壳&#xff09; 制作U盘启动盘&#xff0c;并安装系统 在MSDN i tell you下载Ubuntu20.04 Desktop 版本&#xff0c;并使用Rufus制作UEFI启动盘&#xff0c;参考UEFI安装Ubuntu使用GPTU…

mysql 的MHA

mysql 的MHA 什么是MHA 高可用模式下的故障切换&#xff0c;基于主从复制。 单点故障和主从复制不能切换的问题。 至少需要3台。 故障切换过程0-30秒。 vip地址&#xff0c;根据vip地址所在的主机&#xff0c;确定主备。 主 vip 备 vip 主和备不是优先确定的&#xff…

InternLM Linux 基础知识

完成SSH连接与端口映射并运行hello_world.py 创建并运行test.sh文件 使用 VSCODE 远程连接开发机并创建一个conda环境

“pandas”的坑

参考&#xff1a;百度安全验证 本文基于python第三方数据分析库pandas&#xff0c;分享这几天所遇到的3个爬坑的案例&#xff0c;希望对也在爬坑的同学们尽一份绵薄之力&#xff0c;如有错误或者写得不好的地方&#xff0c;烦请指正&#xff0c;谢谢。 01df中startswith的坑 …

led灯什么牌子的质量好?led灯护眼效果好的五款爆品分享

大家在选择led灯的时候&#xff0c;最关心的就是“led灯什么牌子的质量好&#xff1f;”市面上商家推出来的led灯品牌众多&#xff0c;型号以及功能也是令人眼花缭乱的&#xff0c;既然如此&#xff0c;那我们应该如何买到质量过关又好用的led灯呢&#xff1f;接下来我将为大家…

敏感信息泄露wp

1.右键查看网页源代码 2.前台JS绕过&#xff0c;ctrlU绕过JS查看源码 3.开发者工具&#xff0c;网络&#xff0c;查看协议 4.后台地址在robots,拼接目录/robots.txt 5.用dirsearch扫描&#xff0c;看到index.phps,phps中有源码&#xff0c;拼接目录&#xff0c;下载index.phps …

网页封装app:如何将网站转换为移动应用程序?(网页封装app)

随着移动互联网的普及&#xff0c;越来越多的企业开始关注移动应用程序的开发。但是&#xff0c;对于一些小型企业或个人&#xff0c;开发一款移动应用程序可能需要投入大量的时间和金钱。这时&#xff0c;网页封装app就成了一个不错的选择。 app在线封装www,ppzhu.net 什么是…

【AI人工智能】文心智能体,00后疯感工牌生成器,低代码工作流的简单应用以及图片快速响应解决方案,干货满满,不容错过哦

背景 文心智能体平台&#xff0c;开启新一轮活动&#xff0c;超级创造营持续百日活动。 在AI 浪潮席卷的今天&#xff0c;如雨后春笋般丛生的 AI 应用&#xff0c;昭告着时代风口显然已随之到来。 如何能把握住时代红利&#xff0c;占据风口&#xff0c;甚至打造新风向&#x…