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

Spring框架源码分析一

如何看源码(方法论)

  • 不要忽略源码中的注释

  • 使用翻译工具

  • 先梳理脉络,然后梳理细节即总分总,先总体过一遍,再看细节,再做一个总结

  • 大胆猜测(8分靠猜),小心验证,再调整思路

  • 坚持、坚持、坚持

  • 遇到不会的,先迈过去,先不处理

坦白说看源码就是为了工作或为了技能的提升,被迫做这样的事情;

一定要掌握技巧,刚开始会很痛苦,在收获成就感之后才会慢慢产生兴趣,有了兴趣,再坚持就容易很多。

Spring IOC和AOP

原来想使用某一个对象,必须自己去new,现在spring帮我们管理和创建这些对象,这些过程不需要我们去做了,如果要用直接从容器中拿可以了。

spring创建对象大致思路(粗粒度)

看源码之前先理思路,先从spring xml方式创建对象开始,

id class是指我们要创建的那些bean对象,

第一步先读取配置文件,把它加载到当前应用程序里面去,

第二步通过解析知道有什么样的属性值、属性名称,

把这些信息都解析完成之后,再创建实例即一个具体的对象,创建出来之后,就可以直接使用了,使用完之后,还有一个销毁的过程。

再从粗粒度中拆分出一些具体细节的点

Spring里面有IOC (控制反转) 和AOP,容器是用来存放bean对象的,那用什么样的数据结构来存?

可以用list、set、map,这三个最大的区别是存取值的方式不一样,

在整个容器里面会存放n多对象,在后面使用的时候,根据一些描述来取出具体的一个值,这个时候就意味着我要根据名字来取出具体value值,所以它最终存储的是k-v格式的数据,这时候只能用map结构存储。

当把这些前置知识都搞明白了,再来细化具体的过程,spring到底是如何进行架构设计的?

当new一个对象的时候或通过其他方式创建对象的时候,才能存储到IOC容器中,存完之后,后面才能取。

这里面会涉及到创建对象的方式,创建对象有几种方式:

  • 第一个是new

  • 第二个是反射

在这些基础之上可以利用一些设计模式,比如用工厂模式创建对象,但不管什么样的方式,最终是要创建对象的。

创建对象的时候要思考另外一个非常核心的点,你创建出来的对象是一个通用的?还是每次都是新的?

spring bean默认的scope作用域是单例的,当然可以指定protype,但是一般情况下没有做特殊指定的话默认就是单例的,也可以指定request或session。

因为每次都new一个新的就不是一个单例对象了,所以spring就放弃了new的方式创建对象。

那反射怎么写代码

1、第一步先获取一个Class clazz=class.forName();

参数是类名.class或对象名.getClass

2、生成具体的对象

Constructor ctor= clazz.getDeclareConstructor()获取构造器,当有了构造器之后,Object obj=ctor.newInstance就可以返回一个具体对象了。

bean的描述信息或定义信息(名字、哪个class、有哪些property) 都会进行相关的存储,当这些东西都定义好之后,容器就可以启动了:

第一步先进行相关的加载,加载完之后进行一个相关的解析工作。

把它对应的一些描述信息(bean的定义信息)转换成一个具体的对象,因此定义一个接口叫BeanDefinition来表示bean的定义信息。

原来的时候是在注解或xml文件里面配置,现在加载到当前容器里面去了。

springboot用的yaml或property配置文件,属于另外一个类型的配置文件了,哪怕是json里面也可以定义bean的描述信息,只要对json进行解析就可以了。

不同的文件需要进行不同的解析工作,中间要进行一个抽象层,抽象存在的意义是定义一些相关的规范或者定义一些相关的方法,由对应的方法来完成具体的解析工作 ,那么再由具体的实现子类去进行相关的一个实现就可以了。

解析xml文件,定义一个xml的读取类;解析json文件,定义一个json的读取类;新的配置文件,依然可以定义新的实现类进行相关的读取和解析工作,这个读取的抽象类就是BeanDefinitionReader,专门用来完成读取的工作。

当还需要一些其他的配置文件的时候,只需要创建具体的子类实现这个接口进行解析就可以了,解析完之后,有一个统一的出口都放到BeanDefinition中去,就相当于提前做了一个抽象,这层抽象来完成具体对应的一个功能,此时已经有了bean的定义信息了,下一步就要把当前这个bean进行一些实例化工作,

通过这种方式可以获取到一个具体的bean对象,当我在获取bean对象的时候,是直接从当前容器里面拿的,拿的前提是一定要有。

想获取都一个完整的对象,一般包含2部分操作,第一部分叫实例化,还有一个叫初始化,实例化在堆中开辟一块空间,属性都是默认值;初始化是给属性赋值,赋值完之后已经变成一个完整对象了,就可以直接拿过来使用了。给属性赋值的操作也分为2个操作,第一个叫填充属性,另外一个叫执行初始化方法。

python中的__new__表示创建了对象,但是属性没有赋任何值,__init 完成了赋值操作;

java中没有明确的这样的一个划分,所以它包含两部分,第一个是填充属性,就表示说调用set方法给属性填充值,当把具体的一个属性填充完成之后,可以调用一个方法叫init-method,执行这个属性指定的方法里面具体实现的一个逻辑。

bean对象里面这样使用init-method和destroy-method。

实例化后下面的某个环节应该包含初始化操作,当对应的初始化完成了之后,获取到一个最终的完整对象,有了完整对象之后就可以进行一个相关的使用了。

spirng是一个框架,除了框架之外还有一点叫生态,springboot或springcloud都是在spirng基础之上演变过来的 或扩展出来的,所以在设计spring源码的时候要注意一件事情,要考虑一个非常主要的点叫扩展性,只有扩展性设计好了,后面才能随意发挥。spring框架在在整个生态里面代表的是基石或叫底层支撑。

http://www.lryc.cn/news/38176.html

相关文章:

  • CSS常用内容总结(扫盲)
  • Java启蒙之语言基础
  • 数据库系统--T-SQL数据查询功能-多表查询(超详细/设计/实验/作业/练习)
  • Spring Boot 3.0系列【14】核心特性篇之Configuration相关注解汇总介绍
  • [ubuntu][jetson]给jetson增加swap空间类似于给windows加虚拟内存
  • 小黑子—Java从入门到入土过程:第二章
  • ElasticSearch搜索详细讲解与操作
  • web实现太极八卦图、旋转动画、定位、角度、坐标、html、css、JavaScript、animation
  • 【LeetCode】33. 搜索旋转排序数组、1290. 二进制链表转整数
  • IBM Semeru Windows 下的安装 JDK 17
  • Lambda表达式和steram流
  • 面试必会-MySQL篇
  • Hadoop入门常见面试题与集群时间同步操作
  • JS 数组去重的方法
  • PMP项目管理项目沟通管理
  • 2.JVM常识之 运行时数据区
  • 你的游戏帐号是如何被盗的
  • C++11异步编程
  • 20230310----重返学习-DOM元素的操作-时间对象-定时器
  • 江苏专转本转本人后悔排行榜
  • 【算法时间复杂度】学习记录
  • 汽车车机芯片Linux系统内核编译问题总结
  • Android13 音量曲线调整
  • OpenHarmony通过MQTT连接 “改版后的华为IoT平台”
  • SQS (Simple Queue Service)简介
  • 高速PCB设计指南系列(三)
  • 【C++】C++11——左右值|右值引用|移动语义|完美转发
  • [ROC-RK3399-PC Pro] 手把手教你移植主线Buildroot(基于2023.02-rc3版本)
  • 重温线性代数
  • 2023河北沃克HEGERLS甘肃金昌重型仓储项目案例|托盘式四向穿梭车智能密集存储系统在工业行业的创新应用