SpringIOC源码阅读笔记(4)

Spring中Bean的生命周期源码分析 从服务的启动到服务的关闭整个流程下来梳理了Bean的整个生命周期,根据这个生命周期自己可以根据这个流程对Spring中容器的实现和Bean的注入流程有了更深的了解,更多细节的部分可以根据一下的源码流程进行debug,毕竟debug看源码是最快的,debug的方式可以知道在每一步入参和出参的结果,以及每一步的正向流程。 阅读详情

上文讲到parsePropertySubElement,分析完这个方法,接着在parseBeanDefinitionElement向下分析:

public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
				parsePropertyElement((Element) node, bd);
			}
		}
	}
public void parsePropertyElement(Element ele, BeanDefinition bd) {
    // 获取 name 属性
    String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
    //如果没有name属性报错
    if (!StringUtils.hasLength(propertyName)) {
        error("Tag 'property' must have a 'name' attribute", ele);
        return;
    }
    //加入解析状态
    this.parseState.push(new PropertyEntry(propertyName));
    try {
        // 如果存在相同的 name ,报错
        if (bd.getPropertyValues().contains(propertyName)) {
            error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
            return;
        }
        // 解析属性值
        Object val = parsePropertyValue(ele, bd, propertyName);
        // 创建 PropertyValue 对象
        PropertyValue pv = new PropertyValue(propertyName, val);
        parseMetaElements(ele, pv);
        pv.setSource(extractSource(ele));
        // 添加到 PropertyValue 集合中
        bd.getPropertyValues().addPropertyValue(pv);
    } finally {
        this.parseState.pop();
    }
}

逻辑其实跟constructor-arg子元素步骤一样。
接下来是parseQualifierElements,如果类型注入产生歧义,可以用名字注入
方法都差不多

public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) {
				parseQualifierElement((Element) node, bd);
			}
		}
	}
public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
//解析type属性
		String typeName = ele.getAttribute(TYPE_ATTRIBUTE);
		if (!StringUtils.hasLength(typeName)) {
			error("Tag 'qualifier' must have a 'type' attribute", ele);
			return;
		}
		this.parseState.push(new QualifierEntry(typeName));
		try {
			AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName);
			qualifier.setSource(extractSource(ele));
			//// 解析 value 属性,并设置到 AutowireCandidateQualifier 中
			String value = ele.getAttribute(VALUE_ATTRIBUTE);
			if (StringUtils.hasLength(value)) {
				qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
			}
			NodeList nl = ele.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
					Element attributeEle = (Element) node;
					String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE);
					String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE);
					if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) {
						BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue);
						attribute.setSource(extractSource(attributeEle));
						qualifier.addMetadataAttribute(attribute);
					}
					else {
						error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle);
						return;
					}
				}
			}
			// 添加到 qualifiers 中
			bd.addQualifier(qualifier);
		}
		finally {
			this.parseState.pop();
		}
	}

至此,已经完成了Document到BeanDefinitionHolder的转变。
沿着processBeanDefinition方法,下一步到了

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
		return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
	}

这是关于自定义标签的解析,

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = definitionHolder;

		// Decorate based on custom attributes first.
		NamedNodeMap attributes = ele.getAttributes();
		//遍历属性,查看是否有适用于装饰的属性
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}

		// Decorate based on custom nested elements.
		//遍历子节点,查看是否有适用于修饰的【子节点】
		NodeList children = ele.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
			}
		}
		return finalDefinition;
	}
	public BeanDefinitionHolder decorateIfRequired(
			Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
		//获取自定义标签的命名空间
		String namespaceUri = getNamespaceURI(node);
		//如果是默认命名标签,直接过滤
		if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
		//找到对应的处理器
			NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
			//进行修饰处理,具体修饰处理见下文中的自定义处理
			if (handler != null) {
				BeanDefinitionHolder decorated =
						handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
				if (decorated != null) {
					return decorated;
				}
			}
			else if (namespaceUri.startsWith("http://www.springframework.org/")) {
				error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
			}
			else {
				// A custom namespace, not to be handled by Spring - maybe "xml:...".
				if (logger.isDebugEnabled()) {
					logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
				}
			}
		}
		return originalDef;
	}

接下来是注册解析的BeanDefinition环节:

public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		//注册beanName
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		//注册alias
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

注册beanName

@Override
private boolean allowBeanDefinitionOverriding = true;

/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
/** List of bean definition names, in registration order. */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
/** List of names of manually registered singletons, in registration order. */
private volatile Set<String> manualSingletonNames = new LinkedHashSet<>(16);
/** Cached array of bean definition names in case of frozen configuration. */
@Nullable
private volatile String[] frozenBeanDefinitionNames;
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		//校验 beanName 与 beanDefinition 非空
		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
			//校验 BeanDefinition
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition oldBeanDefinition;
		//从缓存中获取指定 beanName 的 BeanDefinition
		oldBeanDefinition = this.beanDefinitionMap.get(beanName);
		
		if (oldBeanDefinition != null) {
		//如果存在但是不允许覆盖,抛出异常
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
						"': There is already [" + oldBeanDefinition + "] bound.");
			}
			//覆盖 beanDefinition 大于 被覆盖的 beanDefinition 的 ROLE ,打印 info 日志
			else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (this.logger.isWarnEnabled()) {
					this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							oldBeanDefinition + "] with [" + beanDefinition + "]");
				}
			}
			//// 覆盖 beanDefinition 与 被覆盖的 beanDefinition 不相同,打印 debug 日志
			else if (!beanDefinition.equals(oldBeanDefinition)) {
				if (this.logger.isInfoEnabled()) {
					this.logger.info("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			// 其它,打印 debug 日志
			else {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			// 允许覆盖,直接覆盖原有的 BeanDefinition 到 beanDefinitionMap 中
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		else {
		//检测创建Bean阶段是否已经开启,如果开启了就需要对beanDefinitionMap 进行并发控制
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
				// 添加到 BeanDefinition 到 beanDefinitionMap 中。
					this.beanDefinitionMap.put(beanName, beanDefinition);
					// 添加 beanName 到 beanDefinitionNames 中
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					// 从 manualSingletonNames 移除 beanName
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				this.manualSingletonNames.remove(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}
		//重新设置 beanName 对应的缓存
		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}
@Override
	public void registerAlias(String name, String alias) {
		Assert.hasText(name, "'name' must not be empty");
		Assert.hasText(alias, "'alias' must not be empty");
		// name == alias 则去掉alias
		if (alias.equals(name)) {
			this.aliasMap.remove(alias);
		}
		else {
		// 获取 alias 已注册的 beanName
			String registeredName = this.aliasMap.get(alias);
			if (registeredName != null) {
			//无需重复注册
				if (registeredName.equals(name)) {
					// An existing alias - no need to re-register
					return;
				}
				//不相同且不允许覆盖,抛出错误
				if (!allowAliasOverriding()) {
					throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
							name + "': It is already registered for name '" + registeredName + "'.");
				}
			}
			//检验是否有循环
			checkForAliasCircle(name, alias);
			//注册到map中
			this.aliasMap.put(alias, name);
		}
	}

三.alias

protected void processAliasRegistration(Element ele) {
		String name = ele.getAttribute(NAME_ATTRIBUTE);
		String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
		boolean valid = true;
		if (!StringUtils.hasText(name)) {
			getReaderContext().error("Name must not be empty", ele);
			valid = false;
		}
		if (!StringUtils.hasText(alias)) {
			getReaderContext().error("Alias must not be empty", ele);
			valid = false;
		}
		if (valid) {
			try {
				getReaderContext().getRegistry().registerAlias(name, alias);
			}
			catch (Exception ex) {
				getReaderContext().error("Failed to register alias '" + alias +
						"' for bean with name '" + name + "'", ele, ex);
			}
			getReaderContext().fireAliasRegistered(name, alias, extractSource(ele));
		}
	}

原理其实跟刚才解析bean中的alias相同。

四.嵌入式beans标签

其实就是递归调用注册BeanDefinition。

Creo模型装配总结 creo7.0的零件装配操作方法,建立基准面、新建约束、约束顺序 阅读详情

相关推荐

HFSS线圈仿真避坑指南:从建模到寄生参数分析的完整流程

本文详细介绍了HFSS线圈仿真的完整流程,从精准建模到寄生参数优化,特别针对Ansys Electronics Desktop用户提供实用指南。涵盖线圈几何构建、材料属性配置、端口激励设置及寄生电阻与电感分析等关键步骤,帮助工程师避免常见错误,提升仿真精度与效率。

weixin_29209801的博客 550

Abaqus错误提示:XX elements have missing property definitions._51CAE_新浪博客

提交Abaqus分析任务时,经常会遇到下面一个错误: XXelements have missing property definitions. The elements have been identified in element set ErrElemMissingSection. 经查阅相关网络资料以及多次实践,将可能导致该错误的原因归纳如下,供排查、解决问...

TQT_CAE的博客 6万+

【WB32库开发】第9章 TIM1高级定时器——输出多路PWM

PWM(Pulse Width Modulation)意为脉冲宽度调制,简称脉宽调制 。在工控行业,PWM信号可以用来调节电机转速、调节变频器以及BLDC电机驱动等;在LED照明行业,可以通过PWM来控制LED的亮暗变化;还可以通过PWM信号来控制无源蜂鸣器发出简单的声音等。 WB32也可输出PWM,需配置WB32上的定时器。 在WB32中有4个定时器,其中TIM1为高级定时器,TIMx(2-4)为通用定时器,这四个定时器均挂载在APB1总线上,每个定时器都可以输出4路PWM。 本章需要使用固件库TIM例程

北海村夫的博客 4637

Abaqus中遇到的相关问题

1、Abaqus中初始步中interactions接触对不可批量删除,只能一个一个叉 办法: 在abaqus命令窗里执行下语句,model-name代表模型名称,mdb.models['model-name'].interactions.keys()代表所有接触对的名称,也可以将该语句替换为[CP-1,CP-2,...CP-n],如此批量删除 mdb.models['model-name']...

得之我幸 1万+

Immich vs Nextcloud照片管理实测:自建私有云相册到底选哪个?

本文深度评测了Immich与Nextcloud在私有云相册管理中的表现,涵盖核心功能、性能基准、本土化实践及进阶功能。Immich凭借微服务架构和AI优化在照片管理、移动端体验上表现优异,而Nextcloud则强在生态整合。文章还提供了Docker部署优化和国内网络适配方案,帮助用户根据需求选择最佳方案。

seed的博客 331

我的AI个人公司成立:基于Skills与Qwen大模型的智能问答平台实战开发+龙虾团队

微学AI推出数字员工矩阵,包含10个核心AI角色(总经理、秘书、工程师等),每个角色具备专属技能模块。系统采用FastAPI+Vue3技术栈,核心功能包括:基于SkillLoader的动态技能管理(支持脚本执行和文档加载)、WebSocket流式输出、多轮对话上下文管理。通过模块化架构实现AI自驱协作,可自主完成从需求分析到开发落地的全流程。项目亮点在于声明式技能配置和实时交互能力,打破传统办公壁垒,提升工作效率。

微学AI的博客 1625

ABAQUS ERROR

1xxxxx elements have missing property definitions. The elements have been identified in element set ErrElemMissingSection。 解决: 1 《ABAQUS有限元分析常见问题解答(问题+答案)》P67 2

qq_41998295的博客 6658

久坐不慌,健康护航 —— 智能震动提醒坐垫的设计与实现

硬件核心:选用 ESP32 为主控,HX711 + 应变片实现精准压力检测,8050 三极管驱动震动马达,锂电池 + TP4056 满足便携供电需求;软件逻辑:核心是 “压力阈值判断 + 时间计时”,达到久坐阈值后触发震动提醒,流程图清晰体现了循环检测、状态重置的核心逻辑;代码特性:代码注释完善,阈值可灵活调整,支持串口调试,新手可直接编译烧录并根据实际场景校准。

weixin_42300449的博客 401

‘Element‘ is missing the following properties from type ‘HTMLElement‘: accessKey, accessKeyLabel

Typescript 在TS文件里使用document.getElementsByClassName报错:Type 'Element' is missing the following properties from type 'HTMLElement': accessKey, accessKeyLabel, autocapitalize, dir, and 116 more.ts在使用document.getElementsByClassName,document.querySelector的时候,获取到

LlanyW的专栏 1703

[RAM] DRAM 导论:DDR4 | DDR5 | LPDDR5 | GDRR6 | HBM 应运而生

有数据的地方就有存储, 内存是谁都离不开的产品。而动态随机存取存储器(DRAM)作为一种常见的内存。本博客将介绍DRAM的基本概念、工作原理、优缺点以及应用领域等方面。

串起点滴 3920

一文读懂 STAR-CCM+:多物理场仿真王者,从入门到精通全攻略(附实战路线)

STAR-CCM+是西门子旗下的多物理场仿真平台,集流体、传热、结构、电磁等耦合求解于一体。其核心优势包括:全自动网格处理技术(支持十亿级网格)、多物理场无缝耦合、CPU/GPU并行加速计算、流程自动化与设计探索等。广泛应用于汽车(空气动力学优化、电池热管理)、航空航天(气动设计、发动机仿真)、能源(风电叶片流固耦合)、电子(芯片散热)等行业。相比ANSYS Fluent和OpenFOAM,STAR-CCM+在多物理场耦合和复杂几何处理方面更具优势,适合工业级高精度仿真需求。学习路径建议从基础操作入手,逐步

源代码杀手的博客 341

SpringIOC源码阅读笔记(1)

刚看完springMVC的源码,感觉spring的容器源码还是掌握不到位,所以打算写一点笔记再理一遍思路。 一.Resource spring给资源提供了封装,根据不同的资源类型有不同的实现类,首先先看下UML图: 1.org.springframework.core.io.InputStreamSource 顶层接口,其中就定义了一个方法获取输入流: InputStream getInputStream() throws IOException 2.org.springframework.core.io

jacobbbbbbbb的博客 304

uniapp | vue2 | vue3 - 解决调用天地图功能服务时 http 网络请求报错 net::ERR ABORTED 503(Service Temporarily Unavailabl)

vue,uni-app,天地图,请求报错,503,请求失败,map.tianditu,天地图503,天地图请求503,接口503错误怎么办,vue天地图,uniAPP天地图,获取定位接口服务器报错503,获取当前定位,定位功能,IP属地定位,天地图服务器报错,如何解决报错,net::ERRABORTED503(ServiceTemporarilyUnavailabl),GET,POST,服务暂时不可用,react天地图,一直等待吗,报错怎么办,定位报错,轨迹,经纬度,天地图服务器503,在vue2

🏆 前端领域优质创作者 4438

SpringIOC源码阅读笔记(10)

分析完BeanFactory容器的加载,接下来看一下更复杂的容器ApplicationContext的加载,这个容器也是我们目前使用比较多的容器。跟BeanFactory比起来,ApplicationContext有如下区别: 1.继承 MessageSource,提供国际化的标准访问策略。 2.继承 ApplicationEventPublisher ,提供强大的事件机制。 3.扩展 ResourceLoader,可以用来加载多个 Resource,可以灵活访问不同的资源。 4.对 Web 应用的支持。

jacobbbbbbbb的博客 214

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Spring源码阅读 -- > SpringIOC初始化流程

Spring IOC容器初始化

xinyu 234

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

SpringIOC源码阅读笔记(3)

上篇笔记写到解析element分为解析默认标签以及自定义标签,本文就先从默认标签开始。 public static final String IMPORT_ELEMENT = "import"; public static final String ALIAS_ATTRIBUTE = "alias"; //bean public static final String BEAN_ELEMENT = BeanDefinitionParserDelegate.BEAN_ELEMENT; public stati

jacobbbbbbbb的博客 199

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

如何有效的阅读JDK源码

阅读Java源码的前提条件: 1、技术基础 在阅读源码之前,我们要有一定程度的技术基础的支持。 假如你从来都没有学过Java,也没有其它编程语言的基础,上来就啃《Core Java》,那样是很难有收获的,尤其是《深入Java虚拟机》这类书,或许别人觉得好,但是未必适合现在的你。 比如设计模式,许多Java源码当中都会涉及到。再比如阅读Spring源码的时候...

dl185249965的博客 243

【Spring】Spring ioc源码学习以及关于阅读源码方式的一些小笔记

spring源码阅读笔记

要继续努力的孤独的博客 390

Spring学习笔记--SpringIOC源码(一)

Spring学习笔记–SpringIOC源码 再查看源码的过程中我们应该遵守定焦原则和宏观原则,抓主线,关注源码结构和业务流程,通过断点、反调、和经验来阅读源码以此来提高培养代码架构思维并深入的理解框架。 SpringIOC容器初始化主体流程 Spring IoC的容器体系 IoC容器是Spring的核⼼模块,是抽象了对象管理、依赖关系管理的框架解决⽅案。Spring 提供了很多的容器,其中 BeanFactory 是顶层容器(根容器),不能被实例化,它定义了所有 IoC 容器 必须遵从的⼀套原则,具体的容

qq_40977467的博客 349

SpringIOC源码阅读笔记(2)

整个ioc的过程可以分为3个步骤: 1.资源定位,根据location找到对应的资源。 2.装载,将资源解析到对应的beanDefinition。 3.注册,将beanDefinition中的对象注册进容器。 给一个简单的例子,后面的分析也将从这个例子中展开 BeanFactory bf= new XmlBeanFactory(new ClassPathResource(“beanFactory.xml”)) classpathresource的定位就不细说了, //XmlBeanFactory的主要实现都

jacobbbbbbbb的博客 192

公开,阿里甩出“源码阅读指南”,原来源码才是最经典的学习范例

但其实真要把源码这东西搞定你得到的东西远比你想象的要多!以上就是阿里SSM源码阅读指南的部分内容了,本着有好东西就拿出来与大家分享的原则,另外我还为大家准备了一份JDK源码速成笔记:且往下看。借着这个机会,今天要与大家分享是来自阿里的SSM源码阅读指南,理论+源码设计模式一应俱全,大家拿到之后就知道,差距不止一点点!方便扩展,为所欲为(Spring是一个框架,同时是一个生态,作为整个生态的基础支撑,最重要的是扩展性)为了不影响大家的阅读体验,就不把篇幅拉太长了,只能展示主要内容,需要面试技巧的朋友点。...

JHIII的博客 168

SpringIOC源码阅读笔记(6)

从本文开始进行bean的加载过程的解析。 同样的我们可以从一行代码开始:MyTestBean bean = (MyTestBean)bf.getBean(“myTestBean”); 首先进入AbstractBeanFactory: @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } 代码很长,可以了解获得Bean的主要流程

jacobbbbbbbb的博客 161

SpringIOC源码阅读笔记(8)

上文讲到了创建bean总共有4种方法,已经分析了2种,分别是supplier获取以及工厂方法获取,接下来讲第三种: protected BeanWrapper autowireConstructor( String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) { return new ConstructorResolver(th

jacobbbbbbbb的博客 187

SpringIOC源码阅读笔记(5)

分析完默认标签的解析,接下来分析自定义标签的解析: 方法的入口是在DefaultBeanDefinitionDocumentReader的parseBeanDefinitions方法中,转到parseCustomElement, @Nullable public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } @Nullable public BeanDefiniti

jacobbbbbbbb的博客 148

SpringIOC源码阅读笔记(7)

创建bean的实现在AbstractAutowireCapableBeanFactory,入口是: @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instanc

jacobbbbbbbb的博客 222

SpringIOC源码阅读笔记(9)

bean的创建的最后一步是初始化bean: protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> {

jacobbbbbbbb的博客 133
上一篇: SpringIOC源码阅读笔记(3)
下一篇: SpringIOC源码阅读笔记(5)
jacobbbbbbbb
博客等级 码龄7年 6粉丝 66原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值