Spring 原理图
2023-04-23 11:51:35 28 举报
Spring-原理图
作者其他创作
大纲/内容
P
步入
Spring 容器对象
doCreateBean(……){ …… createBeanInstance(……); ……}
加载配置信息
这是一个核心的方法,上图中的其余内容都在这个方法之内完成了
这里有一个初始化的策略的方法
resolvePath(){ getEnvironment()}
识别 Bean 的信息
BeanDefinitionReader
抽象层BeanDefinitionReader
在这个方法里创建了 beanDefinitionReader ;获取了所有的 Environment 环境配置设置了资源加载器添加了实体解析器加载了 beanDefinitionReader
obtainFreshBeanFactory() { this.refreshBeanFactory(); }
BeanFactoryPostProcessor
getSystemProperties(){ System.getProperty()}
获取配置信息这就已经看到了图上说的 Environment 接口中有的方法了。到这就不继续进了,开始步出、返回
invokeBeanFactoryPostProcessors(){ invokeBeanFactoryPostProcessors(……);}
这个方法就是进行BeanFactoryPostProcessor的处理
Spring 的架构设计过程
loadBeanDefinitions() { doLoadBeanDefinitions(); }
AbstractEnvironment(){ customizePropertySources();}
Bean 的信息init-method, destory-method,property
实例化
resolveRequiredPlaceholders(path)
Processor
IOC 容器需要的特性1. 放在 IOC 容器中的 Bean 对象要方便查找2. 在默认情况下,Bean 对象都是单例的需要满足上述特性,就需要使用 ConcurrentHashMap 进行存储 Bean 对象相关信息
FactoryBean
获取当前所有的环境信息这里面有一个重要的接口 Environment
配置的 Bean 的信息
instantiate(……){ …… Class<?> clazz = bd.getBeanClass(); …… constructorToUse = clazz.getDeclaredConstructor(); …… instantiateClass(constructorToUse);}
创建一个 标准环境 用来封装环境信息
开始寻找父容器,在 Spring 中有父子容器的概念,子容器中没有实现的方法可以去父容器中找,父容器中没有可以去子容器中找
XXX.PropertiesXXX.YAMLSystem.getProperties
首先是创建了一个集合、两个数组: 1、一个标志已经处理过的对象的集合,避免重复操作 2、BeanFactoryPostProcessor 在工厂类执行前执行的方法 3、BeanDefinitionRegistryPostProcessor 当前类一些定义信息 的处理方法然后是三个类似的代码块 1、判断当前类是否属于 BeanDefinitionRegistryPostProcessor 类型 匹配工厂类中所有类型为 PriorityOrdered 对象 把这些匹配出来的对象加入已经 processedBeans 集合 对这些对象进行处理 处理完后,把进行处理的数组清空 2、处理逻辑基本一样,除了 匹配工厂类中所有类型为 Ordered 对象 然后对这些对象进行处理 3、(else)如果 1、2 都没有能够成功执行执行这里。最后两行是真正执行两个 Processor 的方法
refresh()
读取 Bean的信息
读取对应的 Bean 的配置信息的时候,如果需要人为的修改,可以在此处进行具体操作
总结 :1. 作为一个框架,一定要有很好的扩展性2. Spring提供了什么扩展性? (1)在对象创建之前可以添加某些功能 (2)在容器初始化之前可以添加某些功能 (3)在不同的阶段发出不同的事件,完成一些功能 (4)抽出一堆的接口来帮助扩展3. 面向接口编程
BeanFactoryPostProcessor 的处理
这是这一块的核心方法进行所有 非懒加载 的 单例对象 的实例化
setConfigLocations(){ resolvePath(locations[i])}
这个方法就是进行资源文件的获取、解析
refreshBeanFactory() { createBeanFactory(); }
到这里就可以看到之前说的 DOC 了,这里把配置文件封装在 Document 中返回
loadBeanDefinitions() { XmlBeanDefinitionReader beanDefinitionReader loadBeanDefinitions(beanDefinitionReader); }
这一步就像之前说的,步入StandardEnvironment 的构造是空的,再步入,就进入了父类的构造了
ContextClosedEvent.class.getName();
do…… 是实际做事的方法,
最后在 实例化类 方法里,通过反射创建的 Bean 的对象
XML
这个 parse 就是真正加载配置文件的方法,这里就不往里看了
1.对每个 Bean 对象进行遍历,2.筛选出 不是抽象的、是单例的、不是懒加载的,3. 然后判断该对象是否属于 FactoryBean ,如果 是就使用 FactoryBean 的方法进行处理4. 不属于 FactoryBean 就进行整体的获取
Annotation
1、设置了一个标志位,表示要开始实例化了,2、然后获取了本地定义的 Bean,3、按照配置 Bean 的时候定义的 Depends-on 属性进行执行顺序的排序4、获取单例的 Bean 5、执行 createBean 方法,因为没有 do……,所有这个方法只是做个准备工作,没有实际做事
invokeBeanFactoryPostProcessors(……){ Set<String> processedBeans List<BeanFactoryPostProcessor> regularPostProcessors List<BeanDefinitionRegistryPostProcessor> registryProcessors beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor……); beanFactory.isTypeMatchspan style=\"font-size: inherit;\
实例化的对象普通对象(自己定义信息的对象)
刷新 BeanFactory,如果已经有 BeanFactory 就销毁、再创建 ;没有就直接创建
判断,没有获取过环境信息就创建一个 Environment ;有的话直接返回。
在这个方法中,前面的部分都是一些严密的逻辑判断,中间出现了 doCreateBean 这是要实际做事的方法
在这个方法中,前面的部分都是一些严密的逻辑判断,最后有一个 实例化Bean 的方法
Environment
扩展内容
doLoadDocument() { loadDocument(……); }
loadDocument() { builder.parse(……) }
doLoadBeanDefinitions() { Document doc = doLoadDocument(……); }
抽象层
反射获取对象JAVA8 : Object o = Class.newInstance();JAVA9 : Constructor con = Class.getConstructor; Object obj = con.newInstance();
为了更好的扩展性
配置类
finishBeanFactoryInitialization(……){ beanFactory.preInstantiateSingletons();}
这个方法就是完成实例化的方法
创建 BeanFactory 对象,从这里可以看出实际的 BeanFactory 的类型是DefaultListableBeanFactory
public AbstractAutowireCapableBeanFactory() { ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class); }
……
BeanFactory 和 FactoryBean 异同都是为了用来成产对象的所以在实际运用中,1. 如果只是一个普通的对象,就用 BeanFactory 生产;2. 如果需要创造一些独特的东西,就用 Factory 来实现。
loadBeanDefinitions(beanFactory);
(想要识别 Bean 的配置信息需要实现这个接口)
new ……
preInstantiateSingletons (……){ for (String beanName : beanNames){ …… if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { }else{ getBean(beanName); } } }}
对象工厂
createBeanInstance(……){ …… return instantiateBean(……);}
loadBeanDefinitions() { loadBeanDefinitions(configLocations) }
Spring IOC 的核心 :通过反射创建对象、操作对象
返回
loadBeanDefinitions(Resource resource) { loadBeanDefinitions(new EncodedResource(resource));}
customizePropertySources(){ getSystemProperties() getSystemEnvironment()}
AbstractApplicationContext(){ getResourcePatternResolver();}
观察者模式监听创建对象、刷新容器……监听到后,需要完成相应的操作
createBean(……){ …… doCreateBean(……);}
更像是一个模板的工厂,按照模板生成对象
用来处理一个 bug 的代码
如果想在容器不同的阶段,做不同的事,要怎么处理?观察者模式
三个方法getObject () : 返回一个 Object 对象 isSingleton () : 判断当前对象是否是单例的 getType() : 获取当前对象的类型
Processor 处理器
容器演变过程
BeanFactory 创建过程
Spring 的源码执行流程
getBean(……){ doGetBean(……);}
把 系统配置(SystemProperties) 和 系统环境(SystemEnvironment)都存入配置资源队列(propertySources)
invokeBeanFactoryPostProcessors(beanFactory);
IOC 容器
监听器
实例化对象
简图
为社么要有这么多 Processor?Spring 是一个框架,需要考虑很好的扩展性。可以自定义 Processor ,对当前 Bean 做些增强的功能,来更好的完成整个 Bean 的实例化
doGetBean(……){ …… createBean();}
加载 Bean 的定义信息下面会有很多名为 loadBeanDefinitions 的方法,但是注意参数不同
解析、替换环境变量中的值
BeanFactory
createBeanFactory() { new DefaultListableBeanFactory(); }
getEnvironment()(){ createEnvironment()}
createEnvironment(){ StandardEnvironment();}
instantiateBean(……){ …… getInstantiationStrategy().instantiate(……);}
再进一层,到这里开始利用 IO 流把 XML 文件读取进来了然后看到这个 do…… 方法,Spring 中 do…… 表示真正做事的方法
Bean 的定义信息init-method, destory-method,property
先得到了一个 Bean 的 Class 对象然后获取了 Class 对象的所有构造方法然后把构造器传入一个 实例化类 的方法
beanFactory = this.obtainFreshBeanFactory();
这两个用的较多,且面试常问,需要多理解
忽略依赖这三个接口
finishBeanFactoryInitialization(beanFactory);
instantiateClass(……){ …… return ctor.newInstance(……);}
IOC 容器
这里先判断资源文件是否为空,不为空就存入一个资源文件数组。这个方法就是对资源文件数组进行遍历、处理
工厂模式
获取环境变量,并且解析变量。
创建 BeanFactory 对象,
一直进 loadBeanDefinitions 到这里,这里加载的是 XML 配置文件,然后给 XML 文件设置了一个编码格式
BeanPostProcessor
这一块最核心的方法
ClassPathXmlApplicationContext(){ super(parent);}
在工厂方法执行前调用的处理逻辑
“马士兵教育-连老师-Spring-源码”学习笔记如果喜欢请帮忙点个赞
通过环境对象加载配置文件
通过反射,进行实例化
this.setConfigLocations(configLocations);
容器:反射 + 工厂模式
步入
可以为了自己的需求进行独特的设置
这个方法就是上面那个类的一个父容器,最终的父容器就是 BeanFactory。这个方法其他都是一些属性的初始化,这一句是在获取资源解析器
Bean 对象的实例化
0 条评论
回复 删除
下一页