[源码系列:手写spring] IOC第十三节:Bean作用域,增加prototype的支持
为了帮助大家更深入的理解bean的作用域,特意将BeanDefinition的双例支持留到本章节中,创建Bean,相关Reader读取等逻辑都有所改动。
内容介绍
在Spring中,Bean的作用域(Scope)定义了Bean的生命周期和可见性。包括单例和原型,在本章节中我们将为Bean添加多例的支持,下面是Prototype作用域的几个特征介绍:
1. 多例(Prototype): Bean的prototype作用域表示每次从容器中获取该Bean时都会创建一个新的实例。每个请求或依赖注入都会导致创建一个全新的Bean对象。
2. 不受Spring容器管理: prototype作用域的Bean实例不受Spring容器的管理,容器在创建Bean之后不会再跟踪它。这意味着Spring容器不会负责释放或销毁prototype作用域的Bean。一旦Bean被创建并交给调用者,调用者负责Bean的生命周期,包括销毁。
3. 适用场景: prototype作用域适用于那些每次获取实例时都需要全新状态的Bean,例如,HTTP请求的处理器或线程池中的任务。这样可以确保每次获取的Bean都是独立的,不会影响其他实例。
这里设计到设计模式中的原型模式,形象地说,可以将prototype作用域的Bean比喻为一个不断复制的模具。每次你需要一个新的Bean实例时,Spring容器会根据模具再次制作一个全新的Bean。这个模具本身不受容器管理,而是由你自己管理它的生命周期。这与singleton作用域的Bean不同,后者是像一个单一的实例化对象,由容器管理其生命周期。

prototype作用域
可见prototype类型的bean并不受spring容器的管理,你需要自己负责销毁或释放这些Bean实例,以防止内存泄漏。
代码分支
核心代码
BeanDefinition
private String scope = SCOPE_SINGLETON;
private boolean singleton = true;
private boolean prototype = false;
public static String SCOPE_SINGLETON = "singleton";
public static String SCOPE_PROTOTYPE = "prototype";
public void setScope(String scope) {
this.scope = scope;
this.singleton = SCOPE_SINGLETON.equals(scope);
this.prototype = SCOPE_PROTOTYPE.equals(scope);
}
public boolean isSingleton() {
return this.singleton;
}
public boolean isPrototype() {
return this.prototype;
}
AbstractAutowireCapableBeanFactory#doCreateBean()
...
protected Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
Object bean = null;
try {
bean = createBeanInstance(beanDefinition);
//为bean填充属性
applyPropertyValues(beanName, bean, beanDefinition);
//执行bean的初始化方法和BeanPostProcessor的前置和后置处理方法
initializeBean(beanName, bean, beanDefinition);
} catch (Exception e) {
throw new BeansException("Instantiation of bean failed", e);
}
//注册有销毁方法的bean
registerDisposableBeanIfNecessary(beanName, bean, beanDefinition);
if (beanDefinition.isSingleton()) {
addSingleton(beanName, bean);
}
return bean;
}
...
AbstractAutowireCapableBeanFactory#registerDisposableBeanIfNecessary()
/**
* 注册有销毁方法的bean,即bean继承自DisposableBean或有自定义的销毁方法
*
* @param beanName
* @param bean
* @param beanDefinition
*/
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, BeanDefinition beanDefinition) {
//只有singleton类型bean会执行销毁方法
if (beanDefinition.isSingleton()) {
if (bean instanceof DisposableBean || StrUtil.isNotEmpty(beanDefinition.getDestroyMethodName())) {
registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, beanDefinition));
}
}
}
测试
prototype-bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<bean id="car" class="bean.Car" scope="prototype">
<property name="name" value="Rolls-Royce"/>
</bean>
</beans>
单元测试
public class PrototypeBeanTest {
@Test
public void testPrototype() throws Exception {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:prototype-bean.xml");
Car car1 = applicationContext.getBean("car", Car.class);
Car car2 = applicationContext.getBean("car", Car.class);
System.out.println(car1 == car2);;
}
}
测试结果
false
Process finished with exit code 0
[源码系列:手写spring] IOC第十三节:Bean作用域,增加prototype的支持的更多相关文章
- Spring源码分析 手写简单IOC容器
Spring的两大特性就是IOC和AOP. IOC Container,控制反转容器,通过读取配置文件或注解,将对象封装成Bean存入IOC容器待用,程序需要时再从容器中取,实现控制权由程序员向程序的 ...
- 《四 spring源码》手写springioc框架
手写SpringIOCXML版本 /** * 手写Spring专题 XML方式注入bean * * * */ public class ClassPathXmlApplicationContext { ...
- 从零开始手写 spring ioc 框架,深入学习 spring 源码
IoC Ioc 是一款 spring ioc 核心功能简化实现版本,便于学习和理解原理. 创作目的 使用 spring 很长时间,对于 spring 使用非常频繁,实际上对于源码一直没有静下心来学习过 ...
- 框架源码系列六:Spring源码学习之Spring IOC源码学习
Spring 源码学习过程: 一.搞明白IOC能做什么,是怎么做的 1. 搞明白IOC能做什么? IOC是用为用户创建.管理实例对象的.用户需要实例对象时只需要向IOC容器获取就行了,不用自己去创建 ...
- 《四 spring源码》手写springmvc
手写SpringMVC思路 1.web.xml加载 为了读取web.xml中的配置,我们用到ServletConfig这个类,它代表当前Servlet在web.xml中的配置信息.通过web.xml ...
- Spring源码 20 手写模拟源码
参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...
- 利用递归,反射,注解等,手写Spring Ioc和Di 底层(分分钟喷倒面试官)了解一下
再我们现在项目中Spring框架是目前各大公司必不可少的技术,而大家都知道去怎么使用Spring ,但是有很多人都不知道SpringIoc底层是如何工作的,而一个开发人员知道他的源码,底层工作原理,对 ...
- Spring源码剖析3:Spring IOC容器的加载过程
本文转自五月的仓颉 https://www.cnblogs.com/xrq730 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https ...
- 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)
作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言介绍 一个知识点的学习过程基本分为:运行helloworld ...
- Spring源码剖析2:Spring IOC容器的加载过程
spring ioc 容器的加载流程 1.目标:熟练使用spring,并分析其源码,了解其中的思想.这篇主要介绍spring ioc 容器的加载 2.前提条件:会使用debug 3.源码分析方法:In ...
随机推荐
- CDS标准视图:付款锁定原因描述 I_PaymentBlockingReasonText
视图名称:付款锁定原因描述 I_PaymentBlockingReasonText 视图类型:基础 视图代码: 点击查看代码 //Documentation about annotations can ...
- 用 C# 实现检测系统环境变量 “Path” 中是否有某个值,没有就添加的方法
用 C# 实现检测系统环境变量 "Path" 中是否有某个值,没有就添加的方法: using System; using System.Collections.Generic; u ...
- 注册表判断是否安装微软Edge浏览器
自己摸索的,注册表判断是否安装微软Edge浏览器: bool checkInstalledMsEdge() { try { using(var ieKey = Registry.LocalMachin ...
- DeepSeek本地安装部署(指南)
前言 这两天deepseek出圈了. 今天分享一下,如果在本地电脑部署和运行deepseek,实现AI对话的功能. 访问ollama官网: https://ollama.com/ 下载一个合适自己操作 ...
- IPv6的优势分析
本文分享自天翼云开发者社区<IPv6的优势分析>,作者:没烦恼 IPv6的优势分析 1.更大的地址空间 IPv6中IP地址的长度为128位,其地址容量则达到了2^128个,远远大于IPv4 ...
- Linux中如何将txt文件转为png格式
Linux中如何将txt文件转为png格式 linux将txt文件转为png格式如果文本中没有中文,使用enscript,如果文本包含中文,使用paps命令.但是实际使用中,paps部分版本也不支持中 ...
- lvm相关命令及/etc/fstab开机挂载
名词解释: PV: 物理卷(physicalvolume)物理卷就是指硬盘分区或从逻辑上与磁盘分区具有同样功能的设备(如RAID),是LVM的基本存储逻辑块,但和基本的物理存储介质(如分区.磁盘等)比 ...
- Zabbix Proxy安装及替换Zabbix阿里云源脚本
zabbix proxy安装步骤 说明: Zabbix Proxy使用的是独立的数据库实例,如果放在一起数据容易遭到破坏;Proxy仅仅是一个数据采集的作用,其他的依然是依靠Server端实现,这就会 ...
- 最新demo版|如何0-1开发支付宝小程序之如何调试小程序(二)
上一篇跟大家详细的讲了下开发支付宝小程序前所需要做准备事项,安装了支付宝小程序的开发工具.那么今天就来详细聊一下在小程序开发工具中,我们需要如何调试小程序. 支付宝小程序的调试分为三种,分别是「模拟器 ...
- 正则表达式匹配邮箱,IP地址,URL
参考链接: http://urlregex.com/ 1. 邮箱匹配正则表达式 C# ^(?(")(".+?(?<!\\)"@)|(([0-9a-z]((\.(?! ...
https://github.com/yihuiaa/little-spring