Spring IOC原理

说到spring不得不提其两大特性IOC、AOP,本文主要介绍结合代码看下spring Ioc相关原理,阅读源码若是只是为了看源码效率就会很低,仍是要有必定的目的性,咱们结合着如下的问题去源码中找答案。本篇文章为《图灵学院》课程笔记java

  • Bean工厂是如何产生Bean的
  • Bean的依赖关系是由谁来解决的
  • Bean工厂和应用上下文的区别

以下图spring Ioc的总体架构图中能够看出,Spring启动时读取bean配置信息,并在spring中生成一份相应bean配置注册表,而后会根据注册表实例化Bean,而且装配好bean 之间的依赖关系,为上层应用提供bean实例,其中bean的缓存池是经过hashmap实现的git

bean的构建过程

spring.xml中保存了Bean的描述配置,BeanFactory读取这些配置而后生成bean,这是咱们对ioc原理的通常理解,深刻思考还会有更多问题产生web

  • 哪一个java对象承载了配置信息里的内容
  • 这些承载对象是读取配置文件并装载的
  • 这些装载对象又保存在哪里

BeanDefinition(Bean定义)

ioc 实现中 咱们在xml 中描述的Bean信息最后 都将保存至BeanDefinition (定义)对象中,其中xml bean 与BeanDefinition 程一对一的关系。xml bean中设置的属性最后都会体如今BeanDefinition中spring

因而可知,xml bean中设置的属性最后都会体如今BeanDefinition中。如:缓存

**XML-bean ** BeanDefinition
class beanClassName
scope scope
lazy-init lazyInit
constructor-arg ConstructorArgument
property MutablePropertyValues
factory-method factoryMethodName
destroy-method AbstractBeanDefinition.destroyMethodName
init-method AbstractBeanDefinition.initMethodName
autowire AbstractBeanDefinition.autowireMode
id
name

BeanDefinition 属性结构

BeanDefinitionRegistry(Bean注册器)

在上表中咱们并无看到 xml bean 中的 id 和name属性没有体如今定义中,缘由是ID 其做为当前Bean的存储key注册到了BeanDefinitionRegistry 注册器中。name 做为别名key 注册到了 AliasRegistry 注册中心。其最后都是指向其对应的BeanDefinition。markdown

BeanDefinitionRegistry属性结构架构

BeanDefinitionReader(Bean定义读取)oop

如今咱们了解 BeanDefinition 中存储了Xml Bean信息,而BeanDefinitionRegister 基于ID和name 保存了Bean的定义。接下要学习的是从xml Bean到BeanDefinition 而后在注册至BeanDefinitionRegister 整个过程。学习

上图中能够看出Bean的定义是由BeanDefinitionReader 从xml 中读取配置并构建出 BeanDefinitionReader,而后在基于别名注册到BeanDefinitionRegister中。ui

BeanDefinitionReader结构

  • int loadBeanDefinitions(Resource var1)

基于资源加载beanDefinition并注册到注册器

  • int loadBeanDefinitions(String var1)

    基于资源路径加载beanDefinition并注册大屏注册器

  • BeanDefinitionRegistry getRegistry()

    获取注册器

  • ResourceLoader getResourceLoader()

获取资源装载器

基于示例演示BeanDefinitionReader装载过程

//建立一个简单注册器
BeanDefinitionRegistry register = new SimpleBeanDefinitionRegistry();
//建立bean定义读取器
BeanDefinitionReader reader = new XmlBeanDefinitionReader(register);
// 建立资源读取器
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
// 获取资源
Resource xmlResource = resourceLoader.getResource("spring.xml");
// 装载Bean的定义
reader.loadBeanDefinitions(xmlResource);
// 打印构建的Bean 名称
System.out.println(Arrays.toString(register.getBeanDefinitionNames());
复制代码

Beanfactory(bean 工厂)

有了Bean的定义就至关于有了产品的配方,接下来就是要把这个配方送到工厂进行生产了。在ioc当中Bean的构建是由BeanFactory 负责的。其结构以下:

方法说明:

  • getBean(String)
    • 基于ID或name 获取一个Bean
  • T getBean(Class requiredType) 
    • 基于Bean的类别获取一个Bean(若是出现多个该类的实例,将会报错。但能够指定 primary=“true” 调整优先级来解决该错误 )
  • Object getBean(String name, Object... args)
    • 基于名称获取一个Bean,并覆盖默认的构造参数
  • boolean isTypeMatch(String name, Class<?> typeToMatch)
    • 指定Bean与指定Class 是否匹配

以上方法中重点要关注getBean,当用户调用getBean的时候就会触发 Bean的建立动做,其是如何建立的呢?

演示基本BeanFactory获取一个Bean

#建立Bean堆栈
// 其反射实例化Bean
java.lang.reflect.Constructor.newInstance(Unknown Source:-1)
BeanUtils.instantiateClass()
//基于实例化策略 实例化Bean
SimpleInstantiationStrategy.instantiate()
AbstractAutowireCapableBeanFactory.instantiateBean()
// 执行Bean的实例化方法
AbstractAutowireCapableBeanFactory.createBeanInstance()
AbstractAutowireCapableBeanFactory.doCreateBean()
// 执行Bean的建立
AbstractAutowireCapableBeanFactory.createBean()
// 缓存中没有,调用指定Bean工厂建立Bean
AbstractBeanFactory$1.getObject()
// 从单例注册中心获取Bean缓存
DefaultSingletonBeanRegistry.getSingleton()
AbstractBeanFactory.doGetBean()
// 获取Bean
AbstractBeanFactory.getBean()
// 调用的客户类
com.tuling.spring.BeanFactoryExample.main()
复制代码

Bean建立时序图:

从调用过程能够总结出如下几点:

  1. 调用BeanFactory.getBean() 会触发Bean的实例化。
  2. DefaultSingletonBeanRegistry 中缓存了单例Bean
  3. Bean的建立与初始化是由AbstractAutowireCapableBeanFactory 完成的。

BeanFactory 与 ApplicationContext区别

BeanFactory 看上去能够去作IOC当中的大部分事情,为何还要去定义一个ApplicationContext 呢? ApplicationContext 结构图

从图中能够看到 ApplicationContext 它由BeanFactory接口派生而来,于是提供了BeanFactory全部的功能。除此以外context包还提供了如下的功能:

  1. MessageSource, 提供国际化的消息访问
  2. 资源访问,如URL和文件
  3. 事件传播,实现了ApplicationListener接口的bean
  4. 载入多个(有继承关系)上下文 ,使得每个上下文都专一于一个特定的层次,好比应用的web层

原文地址

cbaj.gitee.io/blog/2020/0…

相关文章
相关标签/搜索