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. 过滤器链&…

富格林:防范虚假可信投资经验

富格林指出&#xff0c;现货黄金投资作为一种全球性的金融衍生品交易&#xff0c;吸引了无数投资者的目光。它不仅具备避险属性&#xff0c;还是资产配置中不可或缺的一部分。然而&#xff0c;要想在市场中防范虚假陷阱&#xff0c;投资者必须要掌握并且利用可信的投资经验。下…

引领安全新风尚: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;成为了许多人寻…

项目中使用多线程

项目中使用多线程 线程池 1、线程池配置 项目中如果要使用线程池&#xff0c;必须先进行配置&#xff0c;如果使用spring 默认的线程池配置可能会导致OOM异常 注意要在spring启动项 上加上EnableAsync 开启异步支持线程池要配置Configuration注解交给spring管理配置线程池主…

SpringMVC笔记详解

SpringMVC 1、SpringMVC简介 1.1、什么是MVC MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分 M&#xff1a;Model&#xff0c;模型层&#xff0c;指工程中的JavaBean&#xff0c;作用是处理数据 JavaBean分为两类&#xff1a; 一类称为实体类Be…

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

linux环境下重新编译opencv的安卓动态链接库opencv_java4.so文件

一、安装java 1.8 #安装依赖 sudo apt-get install python-software-properties sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo add-apt-repository ppa:ts.sch.gr/ppa sudo apt-get update sudo apt-get install oracle-java8-installer 二…

VB中的函数和子程序(Sub)的区别和用法

在VB&#xff08;Visual Basic&#xff09;及其派生语言如VBA&#xff08;Visual Basic for Applications&#xff09;中&#xff0c;函数&#xff08;Function&#xff09;和子程序&#xff08;Sub&#xff09;是两种不同类型的代码块&#xff0c;它们在用途、返回值以及调用方…

前端必知必会-html的id属性和Iframe

文章目录 HTML id 属性类和 ID 之间的区别带有 ID 和链接的 HTML 书签在 JavaScript 中使用 id 属性HTML IframeIframe - 设置高度和宽度Iframe - 删除边框Iframe - 链接的目标总结 HTML id 属性 HTML id 属性用于为 HTML 元素指定唯一 id。id 属性的值在 HTML 文档中必须是唯…

AI推介-大语言模型LLMs论文速览(arXiv方向):2024.07.15-2024.07.20

文章目录&#xff5e; 1.SegPoint: Segment Any Point Cloud via Large Language Model2.LLMs as Function Approximators: Terminology, Taxonomy, and Questions for Evaluation3.Scaling Laws with Vocabulary: Larger Models Deserve Larger Vocabularies4.Large Language …

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

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

微信小程序注册及认证

进行了两个小程序的注册及认证&#xff0c;记录一下 首先&#xff0c;注册小程序通常都是给企业注册&#xff0c;有些资料最好事先准备&#xff0c;考虑到认证、备案的审核&#xff0c;以及对公打款需要走公司内的审批等&#xff0c;整个过程可能需要一到两周的时间。 准备工…

【ffmpeg命令入门】获取音视频信息

文章目录 前言使用ffmpeg获取简单的音视频信息输入文件信息文件元数据视频流信息音频流信息 使用ffprobe获取更详细的音视频信息输入文件信息文件元数据视频流信息音频流信息 总结 前言 在处理多媒体文件时&#xff0c;了解文件的详细信息对于调试和优化处理过程至关重要。FFm…

后端面试题日常练-day11 【Java基础】

题目 希望这些选择题能够帮助您进行后端面试的准备&#xff0c;答案在文末 Java中的String和StringBuffer/StringBuilder有何区别&#xff1f; a) String是不可变的&#xff0c;StringBuffer/StringBuilder是可变的 b) String是线程安全的&#xff0c;StringBuffer/StringBuil…

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 系统功能…