当前位置: 首页 > news >正文

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还有一些其他的设计模式,看到这里面试以及能防得住了,后续再介绍其他的设计模式。

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

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • [红明谷CTF 2021]write_shell 1
  • UE5+OpenCV配置(Windows11系统)
  • Java从基础到高级特性及应用
  • 001.精读《Big Data: A Survey》
  • SVD用于图形处理★★★
  • element ui 修改table筛选按钮为自定义按钮
  • C# Parallel设置最大并发度
  • 【Qwen-Audio部署实战】Qwen-Audio-Chat模型之FastApi部署实战
  • Fréchet Inception Distance(FID)图像生成技术指标
  • 《AM-Bi-LSTM: Adaptive Multi-Modal Bi-LSTM for Sequential Recommendation》
  • MATLAB学习日志DAY23
  • Java | Leetcode Java题解之第283题移动零
  • Git操作指令(已完结)
  • DolphinScheduler学习
  • C++11中的右值引用以及移动构造等
  • 77. Combinations
  • CSS居中完全指南——构建CSS居中决策树
  • docker-consul
  • ES学习笔记(12)--Symbol
  • Git的一些常用操作
  • Joomla 2.x, 3.x useful code cheatsheet
  • Linux后台研发超实用命令总结
  • MobX
  • React 快速上手 - 07 前端路由 react-router
  • Redis的resp协议
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • vue--为什么data属性必须是一个函数
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 京东美团研发面经
  • 跨域
  • 力扣(LeetCode)22
  • 盘点那些不知名却常用的 Git 操作
  • 正则表达式小结
  • 中文输入法与React文本输入框的问题与解决方案
  • ​低代码平台的核心价值与优势
  • !!java web学习笔记(一到五)
  • #if 1...#endif
  • #include
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (个人笔记质量不佳)SQL 左连接、右连接、内连接的区别
  • (计算机网络)物理层
  • (每日持续更新)jdk api之FileReader基础、应用、实战
  • (每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第3章 信息系统治理(一)
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .net打印*三角形
  • .net开发日常笔记(持续更新)
  • .NET之C#编程:懒汉模式的终结,单例模式的正确打开方式
  • .sh 的运行