前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring IOC源码最全分析

Spring IOC源码最全分析

作者头像
Tim在路上
发布2020-08-04 10:32:49
3810
发布2020-08-04 10:32:49
举报

IOC 控制反转

1. Spring IOC 的原理?

spring ioc 即控制反转,就是将我们创建和管理对象交给了spring进行处理; 我们只需要通过配置文件描述对象, 容器加载配置文件描述,并将其转换为Bean Difinition , 然后通过BeanFactory 来生产对象,当然单利在创建一次后会缓存在bean容器中。

Spring IOC 主要实现依赖于 工厂模式 + 反射;

2. Spring IOC 容器有什么?
  1. BeanFactory
  2. ApplicationContext

BeanFactory - BeanFactory 就像一个包含 bean 集合的工厂类。它会在客户端要求时实例化 bean。 ApplicationContext - ApplicationContext 接口扩展了 BeanFactory 接口。它在 BeanFactory 基础上提供了一些额外的功能。

3. Spring load 作为bean定义的过程?

定义bean可以通过xml <bean> 标签的形式进行配置;其次现在使用注解形式进行配置;

  1. 在 @Configuration 类文件中通过 @Bean进行配置
  2. 通过@ComponentScan 包,@server,@controller等进行配置
  3. 通过 @Import进行导入;
@Import // 导入一个普通类到spring容器,可以有几种方式:
  1. @import(value = {InstC.class})
  2. // 通过在注册器中,构造bean定义并通过import导入,spring整合mybatis @import(value = {ImportBeanDifinitionRegister.class})
  3. // 通过类的相对类名,包,可以导入批量,实现importSelector ,springboot 自动装配原理 @imoprt(value = {ImportSelector.class})

加载过程是:

  1. .class 的字节码文件,通过JVM 类加载器加载到内存,
  2. 通过@import,@componentScan,@Bean 等将其转换为Bean Definition,
  3. 将其存储在BeanDefinitionMap 中,key BeanName,value 就是对象;
4. Spring Bean definition 定义 ?

image.png

spring 将配置解析为bean定义:

class: 类路径名

scope: 单利,原型

autowaremode: 注入模型

lazyInit 是否是懒加载

代码语言:javascript
复制
默认注入模型是 0, 在使用的时候必须加@Autoware

可以在后置处理器修改注入模型,1,2 分别是byName, byType, 在类中必须写setXXX方法 它就会自动的注入进去;

懒加载,依赖,构造参数等记录;

5. BeanFactoryPostProcessor

spring 提供一个扩展机会再bean definition 还没进行实例化的时候,还可以对其进行扩展。 修改我们bean definition 的属性;

BeanFactoryPostProcessor 修改的是我们的bean定义,相当于修改的是类型,而不是具体的实例;

代码语言:javascript
复制
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子类,在父类的基础上,增加了新的方法,允许我们获取到BeanDefinitionRegistry,从而编码动态修改BeanDefinition。例如往BeanDefinition中添加一个新的BeanDefinition。

BeanDefinitionRegistryPostProcessor,这也就是我们在@import中实现第二种方法的原理;

也就是在getBean 之前进行调用;

6. BeanPostProcessor
代码语言:javascript
复制
public interface BeanPostProcessor {
    //bean初始化方法调用前被调用
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    //bean初始化方法调用后被调用
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

BeanPostProcessor 是在我们bean进行初始化前后进行工作;

它是在getBean()后对bean进行初始化前后进行调用;

7. spring mvc 启动过程
  1. 创建一个servletContext 容器,将我们 Rootconfig保存到容器中;
  2. 创建一个contextLoaderListener, 注册到 servletContext中;
  3. 创建一个空的子容器,将webConfig,保存到中,setParent(servletContext),将servletContext作为父容器;
  4. 创建一个dispatcherServlet,并将其注册到子容器中
  5. contextLoaderListener,和 dispatcherServlet会进行刷新容器,将bean加载到我们容器中;
8. 容器刷新,创建Bean的过程

spring 容器启动流程:

  1. 刷新容器,标记容器启动
  2. 将配置信息解析,注册到BeanFactory
  3. 实例化BeanFactoryPostProcessor,调用beanFactoryPostProcessor修改bean definition
  4. 注册 beanpostprocessors
  5. 初始化当前的事件广播器
  6. 初始化所有非懒加载单例 singleton beans(lazy-init 的除外) 7.初始化容器的生命周期事件处理器,并发布容器的生命周期事件
代码语言:javascript
复制
@Override
public void refresh() throws BeansException, IllegalStateException {
   synchronized (this.startupShutdownMonitor) {
      // 刷新前准备工作
      prepareRefresh();

      // 调用子类refreshBeanFactory()方法,获取bean factory
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

      // 创建bean Factory的通用设置
      prepareBeanFactory(beanFactory);

      try {
         // 子类特殊的bean factory设置
         postProcessBeanFactory(beanFactory);

         // 实例化beanFactoryPostProcessor
         // 调用beanFactoryPostProcessor修改bean definition
         invokeBeanFactoryPostProcessors(beanFactory);

         // 注册 bean pst processors
         registerBeanPostProcessors(beanFactory);

         // 初始化信息源,和国际化相关
         initMessageSource();

         // 初始化容器事件传播器
         initApplicationEventMulticaster();

         // 调用子类特殊的刷新逻辑
         onRefresh();

         // 为事件传播器注册事件监听器
         registerListeners();

         // 实例化所有非懒加载单例
         finishBeanFactoryInitialization(beanFactory);

         // 初始化容器的生命周期事件处理器,并发布容器的生命周期事件
         finishRefresh();
      }

      catch (BeansException ex) {
         // ...
      }
      finally {
         // ...
      }
   }
}
9. springBean 的生命周期

bean 的生命周期指的是getBean后的生命周期;

spring bean 容器的生命周期流程如下:

  1. Spring 容器根据配置中的 bean 定义中实例化 bean。 2. Spring 使用依赖注入填充所有属性,如 bean 中所定义的配置。
  2. 如果 bean 实现 BeanNameAware 接口,则工厂通过传递 bean 的 ID 来调用 setBeanName()。
  3. 如果 bean 实现 BeanFactoryAware 接口,工厂通过传递自身的实例来调用 setBeanFactory()。
  4. 如果存在与 bean 关联的任何 BeanPostProcessors,则调用 preProcessBeforeInitialization() 方法。
  5. 如果为 bean 指定了 init 方法(<bean> 的 init-method 属性),那么将调用它。
  6. 最后,如果存在与 bean 关联的任何 BeanPostProcessors,则将调用 postProcessAfterInitialization() 方法。 8. bean 实现 DisposableBean 接口,当 spring 容器关闭时,会调用 destory()。
  7. 如果为 bean 指定了 destroy 方法(<bean> 的 destroy-method 属性),那么将调用它

DI大概是这样的,根据我们要获取的BeanName,去IOC容器中找到对应的class,然后实例化出一个代理类对象,然后给这个对象的属性赋值。

10. 展开具体DI依赖注入过程
  1. 获取bean 的name,如果是别名将其转换
  2. 从缓存中取得单利bean
  3. 缓存中没有单利bean,判断是否可以在当前BeanFactory中获取单利bean,否则委托当前容器的父容器去寻找,按名字和类型
  4. 没有的话,创建bean

3.1 判断是不是原型实例,如果是,则抛出创建失败异常,如果不是,下一步。

3.2 检查 BeanDefinition 是否在当前的容器中,如果不在那可能在父类容器中,所以委托父类容器查找,如果还没有,则再上一级容器...递归查找。

3.3 检查这个实例是否是为了类型检查而获取,而不是用来使用,如果是,标记这个bean已经被创建,如果不是,下一步。

3.4 根据 beanName获取 父类的BeanDefinition,并检查该对象类类型,比如不能是抽象类等。

3.5 根据 beanName获取所有该 bean依赖的 Bean集合,如果该集合有值,则遍历DI(递归调用 getBean())该 bean集合里的bean,并把bean注册给当前的bean(维护了一个 map来存放关系)。

3.6 如果3.4中获取的 BeanDefinition是单例,则根据该单例对象和 beanName和 args创建一个实例对象;否则,判断 BeanDefinition是否是原型,如果是则根据 beanName,该对象, args创建一个实例;否则拿到3.4获取的 BeanDefinition对象的生命周期 Scope,然后根据 scope来创建实例对象,参数 (beanName,bd,args)。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • IOC 控制反转
    • 1. Spring IOC 的原理?
      • 2. Spring IOC 容器有什么?
        • 3. Spring load 作为bean定义的过程?
          • 4. Spring Bean definition 定义 ?
            • 5. BeanFactoryPostProcessor
              • 6. BeanPostProcessor
                • 7. spring mvc 启动过程
                  • 8. 容器刷新,创建Bean的过程
                    • 9. springBean 的生命周期
                      • 10. 展开具体DI依赖注入过程
                      相关产品与服务
                      容器服务
                      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档