位置: IT常识 - 正文

爱上源码,重学Spring IoC深入

编辑:rootadmin
回答: 我们为什么要学习源码? 1、知其然知其所以然 2、站在巨人的肩膀上,提高自己的编码水平 3、应付面试 1.1 Spring源码阅读小技巧 1、类层次藏得太深,不要一个类一个类的去看,遇到方法该进就大胆的进 2、更不要一行一行的去看,看核心点,有些方法并不重要,不要跟它纠缠 3、看不懂的先不看 ... 回答:我们为什么要学习源码?1、知其然知其所以然2、站在巨人的肩膀上,提高自己的编码水平3、应付面试1.1 Spring源码阅读小技巧

推荐整理分享爱上源码,重学Spring IoC深入,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

1、类层次藏得太深,不要一个类一个类的去看,遇到方法该进就大胆的进

2、更不要一行一行的去看,看核心点,有些方法并不重要,不要跟它纠缠

3、看不懂的先不看,根据语义和返回值能知道这个方法达到了啥目的即可

4、只看核心接口(下面标注了重点的地方)和核心代码,有些地方也许你使用spring以来都没触发过

5、debug跟步走,源码中给大家标注好了,见到 ”===>“ 就进去

​进去之前,下一行打个断点,方便快速回到岔路口

​进去之前,可以先点方法看源码,再debug跟进

6、广度优先,而非深度优先。先沿着主流程走,了解大概,再细化某些方法

7、认命。spring里多少万行的代码,一部书都写不完。只能学关键点

阅读源码目的

加深理解spring的bean加载过程

面试吹牛x

江湖传说,spring的类关系是这样的……

1.2 IoC初始化流程与继承关系引言在看源码之前需要掌握Spring的继承关系和初始化1) 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、实例化后放到一级缓存(工厂)

2) 容器与工厂继承关系

tips:

别紧张,下面的继承记不住没有关系

关注颜色标注的几个就可以

目标:简单理解ioC容器继承关系

继承关系理解:

1、ClassPathXmlApplicationContext最终还是到了 ApplicationContext 接口,同样的,我们也可以使用绿颜色的 FileSystemXmlApplicationContext 和 AnnotationConfigApplicationContext 这两个类完成容器初始化的工作

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

3、AnnotationConfigApplicationContext 的构造函数扫描classpath中相关注解的类,主流程一样

课程中我们以最经典的 classpathXml 为例。

Bean工厂继承关系

目标:

ApplicationContext 和 BeanFactory 啥关系?

BeanFactory 和 FactoryBean呢?

爱上源码,重学Spring IoC深入

总结:

别害怕,上面的继承关系不用刻意去记住它

其实接触到的就最下面这个!

1.3 开始搭建测试项目

四步:

1、新建测试module项目

首先我们在 Spring 源码项目中新增一个测试项目,点击 New -> Module... 创建一个 Gradle 的 Java 项目

2、详细信息

3、设置gradle

4、完善信息

在 build.gradle 中添加对 Spring 源码的依赖:

compile(project(':spring-context'))

spring-context 会自动将 spring-core、spring-beans、spring-aop、spring-expression 这几个基础 jar 包带进来。

接着,我们需要在项目中创建一个 bean 和配置文件(application.xml)及启动文件(Main.java)

接口如下:

package com.spring.test.service;public interface UserService {public String getName();}

实现类

package com.spring.test.impl;import com.spring.test.service.UserService;public class UserServiceImpl implements UserService {@Overridepublic String getName() {return "Hello World";}}

Main代码如下

public class Test {public static void main(String[] args) {ApplicationContext context =new ClassPathXmlApplicationContext("classpath*:application.xml");UserService userService = context.getBean(UserService.class);System.out.println(userService);// 这句将输出: hello worldSystem.out.println(userService.getName());}}

配置文件 application.xml(在 resources 中)配置如下:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userService" class="com.spring.test.impl.UserServiceImpl"/></beans>

运行

输出如下com.spring.test.impl.UserServiceImpl@2aa5fe93Hello World1.4 工厂的构建引言:接下来,我们就正式讲解Spring ioC容器的源码我们的目的:看一下ioC如何帮我们生成对象的

生命周期

1)ApplicationContext入口

参考 IocTest.java

测试代码:spring支持多种bean定义方式,为方便大家理解结构,以xml为案例,后面的解析流程一致

ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:${xmlName}.xml");// (c)从容器中取出Bean的实例,call:AbstractApplicationContext.getBean(java.lang.Class<T>)//工厂模式(simple)UserService userService = (UserService) context.getBean("userServiceBeanId");// 这句将输出: hello worldSystem.out.println(userService.getName());

进入到ClassPathXmlApplicationContext的有参构造器

org.springframework.context.support.ClassPathXmlApplicationContext#ClassPathXmlApplicationContext(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);//默认为trueif (refresh) {//核心方法(模板)refresh();}}

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

super方法做了哪些事情1、super方法:通过点查看父容器与子容器概念2、super方法:调用到顶端,一共5层,每一层都要与讲义中的【ioC与Bean工厂类关系继承】进行对照3、super方法:在什么地方初始化的类加载器和解析器setConfigLocations方法做了哪些事情:1、如何返回的系统环境和jvm环境2、路径的解析3、设置占位符解析器进入核心方法refresh2)预刷新

prepareRefresh()【准备刷新】

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

讲解重点(断点跟踪、类继承关系、架构图讲解)

prepareRefresh干了哪些事情//1、记录启动时间/设置开始标志//2、子类属性扩展(模板方法)//3、校验xml配置文件//4、初始化早期发布的应用程序事件对象(不重要,仅仅是创建setg对象)3)创建bean工厂【重点】

【获得新的bean工厂】obtainFreshBeanFactory()

最终目的就是解析xml,注册bean定义

关键步骤//1、关闭旧的 BeanFactory//2、创建新的 BeanFactory(DefaluListbaleBeanFactory)//3、解析xml/加载 Bean 定义、注册 Bean定义到beanFactory(未初始化)//4、返回全新的工厂ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();4)bean工厂前置操作

【准备bean工厂】prepareBeanFactory(beanFactory);

//1、设置 BeanFactory 的类加载器//2、设置 BeanFactory 的表达式解析器//3、设置 BeanFactory 的属性编辑器//4、智能注册

tips

当前代码逻辑简单、且非核心

5)bean工厂后置操作

【后置处理器Bean工厂】postProcessBeanFactory(beanFactory) 空方法

tips:子类实现

空方法,跳过

6)工厂后置处理器【重点】

【调用bean工厂后置处理器】invokeBeanFactoryPostProcessors(beanFactory);

//调用顺序一:bean定义注册后置处理器//调用顺序二:bean工厂后置处理器PostProcessorRegistrationDelegate 类里有详细注解

tips

invoke方法近200行

关注两类后置处理器的方法执行步骤和顺序

7)bean后置处理器

【注册bean后置处理器】registerBeanPostProcessors(beanFactory)

//6、【注册bean后置处理器】只是注册,但是不会反射调用//功能:找出所有实现BeanPostProcessor接口的类,分类、排序、注册registerBeanPostProcessors(beanFactory);//核心:查看重要的3步;最终目的都是实现bean后置处理器的注册// 第一步: implement PriorityOrdered// 第二步: implement Ordered.// 第三步: Register all internal BeanPostProcessors.8)国际化

【初始化消息源】国际化问题i18n initMessageSource();

tips:

就加了个bean进去,非核心步骤,跳过

9)初始化事件广播器

【初始化应用程序事件多路广播】initApplicationEventMulticaster();

tips:

需要讲解观察者设计模式

重点:就放了个bean进去, 到下面的 listener再联调。

10)刷新

【刷新】 onRefresh();

空的,交给子类实现:默认情况下不执行任何操作

// 具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)onRefresh();不重要,跳过11)注册监听器【重点】

【注册所有监听器】registerListeners();

测试代码参考:MulticastTest

//获取所有实现了ApplicationListener,然后进行注册//1、集合applicationListeners查找//2、bean工厂找到实现ApplicationListener接口的bean//3、this.earlyApplicationEvents;

tips:

需要讲解观察者设计模式

重点:演示多播和容器发布

12)完成bean工厂【重点】

【完成bean工厂初始化操作】finishBeanFactoryInitialization(beanFactory);

//【完成bean工厂初始化操作】负责初始化所有的 singleton beans//此处开始调用Bean的前置处理器和后置处理器finishBeanFactoryInitialization(beanFactory);

讲解重点(断点跟踪、类继承关系、架构图讲解)

//1、设置辅助器:例如:解析器、转换器、类装载器//2、实例化//3、填充//4、调用前置、后置处理器//核心代码在 getBean() , 下面单独讲解13)完成刷新

【完成刷新】

protected void finishRefresh() {// 1、清除上下文级资源缓存clearResourceCaches();// 2、LifecycleProcessor接口初始化// ps:当ApplicationContext启动或停止时,它会通过LifecycleProcessor来与所有
本文链接地址:https://www.jiuchutong.com/zhishi/304540.html 转载请保留说明!

上一篇:CSS进阶内容—浮动和定位详解(css浮动怎么弄)

下一篇:install PostgreSQL Community Ubuntu Documentation

  • 小米万能遥控怎么调空调制热(小米万能遥控怎么用不了)

    小米万能遥控怎么调空调制热(小米万能遥控怎么用不了)

  • 华为matebook14麦克风没声音是怎么回事(华为电脑mate book 14麦克风在哪)

    华为matebook14麦克风没声音是怎么回事(华为电脑mate book 14麦克风在哪)

  • 抖音作品分类如何设置(抖音怎么进行作品分类)

    抖音作品分类如何设置(抖音怎么进行作品分类)

  • 微信突然不能抢红包了(微信抢不了红包是怎么回事)

    微信突然不能抢红包了(微信抢不了红包是怎么回事)

  • 手机感应器坏了怎么办(手机感应器坏了有什么影响)

    手机感应器坏了怎么办(手机感应器坏了有什么影响)

  • 抖音视频剪辑用什么软件(抖音视频剪辑用什么电脑软件)

    抖音视频剪辑用什么软件(抖音视频剪辑用什么电脑软件)

  • 在Word字处理的编辑过程中,中英文输入法切换用(在word字处理的编辑中一段文字)

    在Word字处理的编辑过程中,中英文输入法切换用(在word字处理的编辑中一段文字)

  • powerpoint中用鼠标连续选取多个选项时用什么键(在powerpoint2010中,可以用鼠标拖动)

    powerpoint中用鼠标连续选取多个选项时用什么键(在powerpoint2010中,可以用鼠标拖动)

  • 华为四摄像头的几款(华为4摄)

    华为四摄像头的几款(华为4摄)

  • 腾讯会议可以截屏吗(腾讯会议可以截屏另一方的手机信息吗)

    腾讯会议可以截屏吗(腾讯会议可以截屏另一方的手机信息吗)

  • 魅族17下巴宽度(魅族17下巴宽度实测)

    魅族17下巴宽度(魅族17下巴宽度实测)

  • 华为平板关闭运行程序(华为平板关闭运行内存)

    华为平板关闭运行程序(华为平板关闭运行内存)

  • 为什么拍照模糊(苹果13为什么拍照模糊)

    为什么拍照模糊(苹果13为什么拍照模糊)

  • 小米10用什么膜(小米10用什么膜最好)

    小米10用什么膜(小米10用什么膜最好)

  • 苹果怎么下载不了网喵(苹果怎么下载不了软件)

    苹果怎么下载不了网喵(苹果怎么下载不了软件)

  • 移动强制停机怎么解除(移动号码被强制停机了怎么申请开机)

    移动强制停机怎么解除(移动号码被强制停机了怎么申请开机)

  • 华为5g芯片叫什么名字(华为5g芯片叫什么)

    华为5g芯片叫什么名字(华为5g芯片叫什么)

  • 爱奇艺账号登录在哪里(怎样退出爱奇艺账号登录)

    爱奇艺账号登录在哪里(怎样退出爱奇艺账号登录)

  • 京东评价怎么粘贴(京东评价怎么粘贴图片)

    京东评价怎么粘贴(京东评价怎么粘贴图片)

  • word中怎么设置参考文献(word中怎么设置首字下沉)

    word中怎么设置参考文献(word中怎么设置首字下沉)

  • soul苹果下载不了(soul下载安装苹果)

    soul苹果下载不了(soul下载安装苹果)

  • 京东预约错了能取消吗(京东预约错了能退吗)

    京东预约错了能取消吗(京东预约错了能退吗)

  • twsi7怎么双耳使用(tws1怎么双耳配对)

    twsi7怎么双耳使用(tws1怎么双耳配对)

  • 手机删除微博能否恢复(手机删除微博能恢复吗)

    手机删除微博能否恢复(手机删除微博能恢复吗)

  • p30能插内存卡吗(华为p30能插内存卡吗)

    p30能插内存卡吗(华为p30能插内存卡吗)

  • 华为nova5i支持超级快充吗(华为nova5支持90帧吗)

    华为nova5i支持超级快充吗(华为nova5支持90帧吗)

  • 怎么知道手机有没有nfc功能(怎么知道手机有没有中病毒)

    怎么知道手机有没有nfc功能(怎么知道手机有没有中病毒)

  • cad格式刷快捷键(中望cad格式刷快捷键)

    cad格式刷快捷键(中望cad格式刷快捷键)

  • Vue项目线上发布,都有缓存不生效怎么办?(vue项目上线教程)

    Vue项目线上发布,都有缓存不生效怎么办?(vue项目上线教程)

  • 抄税是什么意思谁做的事情
  • 支付职工医疗保险怎么查
  • 投资者减除费用和工资薪金减除费用
  • 年度财务报表怎么作废
  • 报关金额多报了3000美金
  • 社保申报后不能缴费
  • 其他业务利润包括哪些科目
  • 企业先租入再出租如何编制会计分录?
  • 预收帐款一直挂账好吗
  • 公司购买汽车保险车船税需要另计吗
  • 外币应收帐款汇兑损益现流附表
  • 样机销售是什么意思
  • 主体资格的法律规定
  • 集团公司向子公司收取管理费的法律规定
  • 折扣发票有什么作用
  • 营改增以后算税公式
  • 混合销售行为的含义及税务处理
  • 已经计提的增值税怎么退
  • 文化事业税收优惠政策
  • 汽车租赁公司产品服务
  • 交易性金融资产的交易费用计入哪里
  • 小规模纳税人的增值税怎么算
  • PHP:mb_ereg_search()的用法_mbstring函数
  • mysql-relay-bin
  • 部分苹果iOS17功能延后推出
  • 公司试乘试驾车管理
  • php字符串定义的三种方式
  • 红字发票只能一张一张开吗
  • 定额备用金的核算可分为哪几类
  • PHP:mcrypt_cfb()的用法_Mcrypt函数
  • 增值税的优惠有哪三种形式
  • vue每一列内容过多自动换行
  • vuejs props
  • 2021年车辆检测
  • 印花税没交会怎么样
  • 增值税进项税如何申报
  • 关闭php报错
  • 支付给临时工的费用
  • 非财政补助结余分配属于什么科目
  • 母子公司关联交易规定
  • 未分配利润分配后在报表如何体现
  • 什么是金融资产和金融负债
  • 企业培训费怎么入账
  • 营业收入的核算方式有哪些
  • 项目提前竣工借款合法吗
  • 汇算清缴怎么弥补亏损怎么操作
  • 实收资本多少年到账
  • 展览门票收入按什么征税
  • 应收账款转营业外支出
  • 购销合同印花税2023年新规定
  • 会计档案销毁方案怎么写
  • 购入旧的固定资产还能一次性抵扣吗
  • win10建行网银盾插上网页弹不出来
  • centos怎么样
  • 优盘和硬盘
  • 进程net1
  • win10的svchost干什么的
  • macbook os x
  • win7虚拟内存如何转移到D盘
  • windows 8.1 with update (multiple editions)
  • win7音量图标不能启用
  • Linux系统中矢量图ai格式怎么打开?
  • 注册表winlogon
  • win10资源管理器启动不了
  • linux mangle
  • linux 11
  • js布尔类型用法
  • js倒计时结束操作
  • shell脚本中执行echo卡住
  • 批处理传输文件夹到ftp
  • opengl教程48讲
  • android设置无标题
  • android四大组件五大布局
  • js全局变量怎么定义
  • 使用jQuery制作动画与特效及插件的应用
  • 以下关于android应用程序的目录结构描述中,不正确的是
  • 网络发票开票系统怎么设置?
  • 税务总局绩效管理四大板块
  • 天津国税发票查询真伪查询
  • 在烟台如何发布招聘信息
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设