Spring ioC源码深入剖析Bean的实例化 1

简介: Spring ioC源码深入剖析Bean的实例化

1 Spring源码阅读技巧

目标:学习阅读源码的技巧(理论+idea)

(重要)源码阅读七大原则:

1、不要一个类一个类的去看

2、更不要一行一行的去看(重点)

3、看不懂的先不看

4、只看核心接口(下面会讲到核心接口)和核心代码(do开头)

5、根据语义和返回值去看

6、ioc (父子容器----对应-父类子类)上下看、带着问题(目标)去看

7、灵活使用工具,将事半功倍(学会看类图ctrl+alt+shift+u、学会看类继承关系ctr+h;方法调用栈+查

找ctr+shift+f)

阅读源码目的

看设计思想!!!

总结:

1、通过理论中的技巧去阅读

2、通过idea自带的功能去辅助阅读


2 ioC初始化流程与继承关系

引言

在看源码之前需要掌握Spring的继承关系和初始化


ioC容器初始化流程

目标:

1、ioC容器初始化过程中到底都做了哪些事情(宏观目标)

2、ioC容器初始化是如何实例化Bean的(划重点,最终目标)

//没有Spring之前我们是这样的
User user=new User();
user.xxx();
//有了Spring之后我们是这样的
<bean id="userService" class="com.spring.test.impl.UserServiceImpl">
User user= context.getBean("xxx");
user.xxx();

ioC流程简化图(七大阶段):

tips:

下面的流转记不住没有关系

在剖析源码的整个过程中,我们一直会拿着这个图和源码对照

初始化:

1、容器环境的初始化

2、Bean工厂的初始化(ioC容器启动首先会销毁旧工厂、旧Bean、创建新的工厂)


读取与定义

读取:通过BeanDefinitonReader读取我们项目中的配置(application.xml)


定义:通过解析xml文件内容,将里面的Bean解析成BeanDefinition(未实例化、未初始化)实例化与销毁Bean实例化、初始化(注入)销毁缓存等


扩展点

事件与多播、后置处理器

复杂的流程学会划重点:

重点总结:

1、工厂初始化过程

2、解析xml到BeanDefinition,放到map

3、调用后置处理器

4、从map取出进行实例化( ctor.newInstance)

5、实例化后放到一级缓存(工厂)


容器与工厂继承关系

tips:

下面的继承记不住没有关系

在剖析源码的整个过程中,我们一直会拿着这个图和源码对照目标:简单理解ioC容器继承关系

继承关系理解:

1、ClassPathXmlApplicationContext最终还是到了 ApplicationContext 接口,同样的,我们也可以

使用绿颜色的 FileSystemXmlApplicationContext 和 AnnotationConfigApplicationContext 这两个类 完成容器初始化的工作


2、FileSystemXmlApplicationContext 的构造函数需要一个 xml 配置文件在系统中的路径,其他和

ClassPathXmlApplicationContext 基本上一样


Bean工厂继承关系

目标:1、简单理解Bean工厂继承关系2、ioc容器与Bean工厂关系?

ApplicationContext 继承了 ListableBeanFactory,这个 Listable 的意思就是,通过这个接口, 我们可以获取多个 Bean,最顶层 BeanFactory 接口的方法都是获取单个 Bean 的。

ApplicationContext 继承了 HierarchicalBeanFactory,获取bean工厂关系.,HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的,也就是每个Bean 有可能有父

Bean

AutowireCapableBeanFactory 这个名字中的 Autowire 大家都非常熟悉,它就是用来自动装配

Bean 用的,但是仔细看上图,ApplicationContext 并没有继承它,不过不用担心,不使用继承, 不代表不可以使用组合,如果你看到 ApplicationContext 接口定义中的最后一个方法getAutowireCapableBeanFactory() 就知道了。

ConfigurableListableBeanFactory 也是一个特殊的接口,看图,特殊之处在于它继承了第二层

所有的三个接口,而 ApplicationContext 没有。这点之后会用到。

总结:上面的继承关系不用刻意去记住它

我们再学习的源码的时候,遇到哪个类,可以和这个图对照

3 Bean是怎么实例化的

引言:

接下来,我们就正式讲解Spring ioC容器的源码

首先,我们要带着问题和目的去阅读;

比如,我们平时玩魔方,

魔方一共6个面,只要我们最终能每个面的颜色弄成一样的就算完成了这就是目的

读源码也是一样的,带着问题、有目的的就看

我们的目的很简单,就是看一下ioC如何帮我们生成对象的


3.1 找到 ioC源码的入口

目标:找到ioC源码的入口

测试代码:进入到Spring源码入口

package com.spring.test;
import com.spring.test.pojo.Person;
import com.spring.test.service.UserService;
import org.springframework.context.ApplicationContext;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
//宏观目标:ioC初始化到底做了哪些事情?
public class Main {
public static void main(String[] args) {
//1、使用注解
//AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Object.class);
//2、使用FileSystemXmlApplicationContext
// ApplicationContext context =new FileSystemXmlApplicationContext("classpath*:application.xml");
///3、使用ClassPathXmlApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:application.xml");
// (c)从容器中取出Bean的实例,call:
AbstractApplicationContext.getBean(java.lang.Class<T>)
//工厂模式(simple)
UserService userService = context.getBean(UserService.class);
// 这句将输出: hello world
System.out.println(userService.getName());
   }
}

进入到ClassPathXmlApplicationContext的有参构造器


org.springframework.context.support.ClassPathXmlApplicationContext#ClassPathXmlApplication Context(java.lang.String[], boolean, org.springframework.context.ApplicationContext)

public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
//继承结构图
//1、返回一个classloader
//2、返回一个解析器
super(parent);
// 1、获取环境(系统环境、jvm环境)
// 2、设置Placeholder占位符解析器
// 2、将xml的路径解析完存储到数组
setConfigLocations(configLocations);
//默认为true
if (refresh) {
//核心方法(模板)
refresh();
   }
}

重点步骤解析(断点跟踪讲解)

super方法做了哪些事情

1、super方法:通过点查看父容器与子容器概念

2、super方法:调用到顶端,一共5层,每一层都要与讲义中的【ioC与Bean工厂类关系继承】进行对照

3、super方法:在什么地方初始化的类加载器和解析器

setConfigLocations方法做了哪些事情:

1、如何返回的系统环境和jvm环境

2、路径的解析

3、设置占位符解析器进入核心方法refresh

4 容器13大模板方法实例化bean

4.1 容器13大模板方法之一:prepareRefresh()

目标:prepareRefresh()到底做了哪些事情

prepareRefresh()【准备刷新】

// synchronized块锁(monitorenter --monitorexit),不然 refresh() 还没结束,
又来个启动或销毁容器的操作
synchronized (this.startupShutdownMonitor) {
//1、【准备刷新】【Did four things】
prepareRefresh();
......。略

1、为什么要加快锁synchronized

2、prepareRefresh干了哪些事情

1、记录启动时间/设置开始标志

2、子类属性扩展(模板方法)

3、校验xml配置文件

4、初始化早期发布的应用程序事件对象(不重要,仅仅是创建setg对象)


4.2 容器13大模板方法之二:obtainFreshBeanFactory()

obtainFreshBeanFactory【获得新的bean工厂】

最终目的就是解析xml,注册bean定义(架构图)(重要)为什么要注册bean定义?


项目中,配置bean(包含但不限于)或者aop的时候,我们可以使用xml

也可以使用注解,所以,在正式的实例化前;先把解析xml(或注解)成bean定义后续,实例化的时候,直接从bean定义去拿

// 2、【获得新的bean工厂】关键步骤
//1、关闭旧的 BeanFactory
//2、创建新的 BeanFactory(DefaluListbaleBeanFactory)
//3、解析xml/加载 Bean 定义、注册 Bean定义到beanFactory(未初始化)
//4、返回全新的工厂
ConfigurableListableBeanFactory beanFactory =obtainFreshBeanFactory();
refreshBeanFactory方法
//1、关闭旧的 BeanFactory
createBeanFactory();方法
//2、创建新的 BeanFactory(DefaluListbaleBeanFactory)
此处解释spring为什么创建DefaultListableBeanFactory?
原来所说的bean工厂就是DefaultListableBeanFactory
//*****************此处需要了解 BeanDefinition类具体干了哪些事情
*************************
loadBeanDefinitions(beanFactory);方法
  // 非常重要,目标如下
// 1、通过BeanDefinitionReade解析xml为Document
// 2、将Document注册到BeanFactory 中(未初始化),
// 经历21个方法;在DefaultListableBeanFactory.registerBeanDefinition注册
//一直都有loadBeanDefinitions方法,直到看到doLoadBeanDefinition
//3、解析xml/加载 Bean 定义、注册 Bean定义到beanFactory(未初始化)
找到到核心方法doLoadBeanDefinitions
//进入,将Document注册到BeanFactory
documentReader.registerBeanDefinitions(doc,
createReaderContext(resource));
将当前资源文件转换成DOM树(registerBeanDefinitions(doc, resource)方法)
//核心,将xml转成的Document注册到BeanFactory
doRegisterBeanDefinitions(root);
//4、返回全新的工厂
这个全新的工厂包含了bean定义以及各种解析器

ps:上面的核心代码由于loadBeanDefinitions做完事情需要经历19个方法,通过断点,介绍核心的

知识点

当前阶段最重要的就是读取xml,然后将xml注册到bean工厂

org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition

代码如下

else {
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// 将 BeanDefinition 放到这个 map 中,这个 map 保存了所有的
BeanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 这是个 ArrayList,所以会按照 bean 配置的顺序保存每一个注册的 Bean 的名
this.beanDefinitionNames.add(beanName);
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
this.manualSingletonNames.remove(beanName);
}
// 这个不重要,在预初始化的时候会用到,不必管它
目录
相关文章
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
1074 26
|
10月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
774 70
|
12月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
1447 0
|
XML 人工智能 Java
Spring IOC 到底是什么?
IOC(控制反转)是一种设计思想,主要用于解耦代码,简化依赖管理。其核心是将对象的创建和管理交给容器处理,而非由程序直接硬编码实现。通过IOC,开发者无需手动new对象,而是由框架负责实例化、装配和管理依赖对象。常见应用如Spring框架中的BeanFactory和ApplicationContext,它们实现了依赖注入和动态管理功能,提升了代码的灵活性与可维护性。
314 1
|
XML Java 数据格式
Spring IoC容器的设计与实现
Spring 是一个功能强大且模块化的 Java 开发框架,其核心架构围绕 IoC 容器、AOP、数据访问与集成、Web 层支持等展开。其中,`BeanFactory` 和 `ApplicationContext` 是 Spring 容器的核心组件,分别定位为基础容器和高级容器,前者提供轻量级的 Bean 管理,后者扩展了事件发布、国际化等功能。
407 18
|
XML Java 数据格式
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
京东一面:spring ioc容器本质是什么? ioc容器启动的步骤有哪些?
|
Java 容器 Spring
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
|
存储 监控 数据可视化
SaaS云计算技术的智慧工地源码,基于Java+Spring Cloud框架开发
智慧工地源码基于微服务+Java+Spring Cloud +UniApp +MySql架构,利用传感器、监控摄像头、AI、大数据等技术,实现施工现场的实时监测、数据分析与智能决策。平台涵盖人员、车辆、视频监控、施工质量、设备、环境和能耗管理七大维度,提供可视化管理、智能化报警、移动智能办公及分布计算存储等功能,全面提升工地的安全性、效率和质量。
403 0