Spring IOC

整体认知Spring体系结构

在这里插入图片描述

IOC的设计原理

IOC的作用

  • bean能够实现集中管理,实现累的可配置和易管理
  • 降低类与类之间的耦合度

    什么是Bean

new出来的叫对象,ioc容器管理的对象称为bean

什么是容器

管理着一个对象的生到死,它就称为这个对象的容器,例如tomcat是servlet的容器,ioc是bean的容器

什么是bean定义

在这里插入图片描述

类如何变成bean

实现方式:

  • xml配置:通过ClassPathXmlApplicationContext获取spring上下文加载ioc容器

  • @注解

  • javaconfig(Spring boot提供):通过AnnotationConfigApplicationContext获取上下文

  • 除了这两个,还有一个FileSystemXmlApplicationContext
    在这里插入图片描述
    在这里插入图片描述

  • (上面的关系图可以在idea通过ctrl+shift+alt+u显示出来)
    底层原理:反射

反射

在这里插入图片描述

掌握Bean生命周期

  • 从关系图可以看出,无论是从哪种方式,顶层都是BeanFactory,因为他们的最终目的都是getBean
  • 这里spring用了工厂模式来规范子类,只要实现BeanFactory(接口)就拥有了创建bean的能力
  • 真正完成创建bean任务的类是AbstractBeanFactory,里面的getBean方法(用了do开头的方法是真正做事的方法,例如doGetBean)
  • 具体要生产什么样的bean需要ClassPathXmlApplicationContext上下文提前收集、扫描(过程中会排除接口和抽象类)好信息,例如scope、lazy等属性
    在这里插入图片描述

拿汽车工厂来做比方

  • BeanFactory只管纯静态和成熟态两个步骤

  • @Bean和< bean />声明的类只是一个概念态,还没有真正生产bean

  • 进入纯静态(生产汽车)之前需要汽车的图纸(定义态),需要把一些定义信息加载出来,即BeanDefinitionMap定义
    在这里插入图片描述

  • 获得Bean定义之后,生产Bean也不是一步到位的(进入纯净态),首先要经过实例化(例如反射上面的无参构造函数实例化,或者被@AutoWired注解依赖注入DI、属性注入),得到个空对象(但并不是所有对象都是空的)

  • 属性依赖注入之后会进行初始化操作(<bean … initMethod="" …/>)

  • 完成生产bean,添加到一级缓存中

  • getBean()操作其实就是在一级缓存中去拿

  • 销毁是调用spring上下问的.close()的时候才会销毁

IOC加载流程

  • 实例化一个ApplicationContext的对象;
  • 调用bean工厂后置处理器完成扫描;
  • 循环解析扫描出来的类信息;
  • 实例化一个BeanDefinition对象来存储解析出来的信息;
  • 把实例化好的beanDefinition对象put到beanDefinitionMap当中缓存起来,以便后面实例化bean;
  • 再次调用bean工厂后置处理器;
  • 当然spring还会干很多事情,比如国际化,比如注册BeanPostProcessor等等,如果我们只关心如何实例化一个bean的话那么这一步就是spring调用finishBeanFactoryInitialization方法来实例化单例的bean,实例化之前spring要做验证,需要遍历所有扫描出来的类,依次判断这个bean是否Lazy,是否prototype,是否abstract等等;
  • 如果验证完成spring在实例化一个bean之前需要推断构造方法,因为spring实例化对象是通过构造方法反射,故而需要知道用哪个构造方法;
  • 推断完构造方法之后spring调用构造方法反射实例化一个对象;注意我这里说的是对象、对象、对象;这个时候对象已经实例化出来了,但是并不是一个完整的bean,最简单的体现是这个时候实例化出来的对象属性是没有注入,所以不是一个完整的bean;
  • spring处理合并后的beanDefinition
  • 判断是否需要完成属性注入
  • 如果需要完成属性注入,则开始注入属性
  • 判断bean的类型回调Aware接口
  • 调用生命周期回调方法
  • 如果需要代理则完成代理
  • put到单例池——bean完成——存在spring容器当中
  • IOC加载流程图: https://www.processon.com/view/5e0a0bb7e4b0250e8afe4230

拓展:BeanFactory和ApplicationContext的区别

在这里插入图片描述

循环依赖

在这里插入图片描述

  • BeanA通过AutoWired注入BeanB,BeanB又通过AutoWired注入A,当BeanA做属性注入时,发现有一个BeanB需要注入,就会先去生产BeanB,生产BeanB时,又会发现有个BeanA需要注入,又去找BeanA,这样就会进入一个死循环,造成循环依赖
  • 解决方法:三级缓存

三级缓存

就是三个Map,在DefaultSingletonBeanRegistry类中

在这里插入图片描述

  • 其实用二级缓存也能解决循环依赖,当BeanA做属性注入时,发现有一个BeanB需要注入,就会先去生产BeanB,此时做个标记放到二级缓存,生产BeanB时,又会发现有个BeanA需要注入,又去找BeanA,此时发现BeanA正在创建,直接返回去
  • 用三级主要责任明确,性能更好
  • 第三级缓存是函数接口,可以利用回调的方式执行,主要用来解决AOP
  • 第一个map(一级缓存)用来存已经new好的Bean
  • 第二个map(二级缓存)和第三个map(三级缓存)其中一个作用是处理循环依赖的

拓展接口

BeanFactoryPostProcessor

bean工厂后置处理器
可以修改bean定义(在扫描完之后、生产bean之前修改)
在这里插入图片描述

idea按ctrl+alt+b查看子接口可看到该接口下还有子接口
在这里插入图片描述

BeanDefinitionRegistryPostProcessor

bean定义注册后置处理器,继承bean工厂后置处理器,但有属于自己的功能,可以注册bean定义的能力(在扫描完之后、生产bean之前注册)
例如spring集成mybatis,mybatis的mapper是个接口不能实例化,在扫描的时候会被排除掉,不能变为bean定义,此时可以用BeanDefinitionRegistryPostProcessor将mapper注册成动态代理

BeanPostProcessor

bean后置处理器,有九个
在这里插入图片描述

分别干预bean的整个生产过程(实例化前、实例化时、实例化后、依赖注入前、依赖注入时、依赖注入后、初始化前、初始化时、初始化后)

  • 在bean初始化完之后,bean的后置处理器会去创建aop(底层原理:动态代理,分别是jdk动态代理和CGLIB动态代理),实现类是AbstractAutoProxyCreator
  • BeanPostProcess接口定义了一个"之前",一个"之后",从"之后"接口方法postProcessAfterInitialization=>实现类AbstractAutoProxyCreator=>调用wrapIfNecessary=>createProxy=>getProxy=>createAopProxy.getProxy接口,按住ctrl+alt+b,即可看到两个实现类CglibAopProxy和jdkDynamicAopProxy
  • 核心代码:jdk创建动态代理的实现Proxy.newProxyInstance

在这里插入图片描述

源码

下载地址

https://github.com/spring-projects/spring-framework

Factorybean与Beanfactory区别

BeanFactory 是ioc容器的底层实现接口,是ApplicationContext 顶级接口

  • spring不允许我们直接操作 BeanFactory bean工厂。
  • BeanFactory 是顶层容器(根容器),不能被实例化,它定义了所有 IoC 容器 必须遵从的⼀套原则,具体的容器实现可以增加额外的功能。所以为我们提供了ApplicationContext 这个接口 此接口继成BeanFactory 接口,ApplicationContext包含BeanFactory的所有功能,同时还进行更多的扩展。
  • BeanFactory 接口又衍生出以下接口
  • 比如我们常看到的ApplicationContext,其下更具体的实现如 ClassPathXmlApplicationContext 包含了解析 xml 等⼀系列的内容,
  • AnnotationConfigApplicationContext 则是包含了注解解析等一系列的内容。Spring IoC 容器继承体系非常聪明,需要使用哪个层次用哪个层次即可,不必使用功能大而全的

在这里插入图片描述

CongihuableApplicationContext 中添加了一些方法:

在这里插入图片描述

主要作用在ioc容器进行相应的刷新,关闭等操作

在这里插入图片描述

FactoryBean 是spirng提供的工厂bean的一个接口

  • FactoryBean 接口提供三个方法,用来创建对象,FactoryBean 具体返回的对象是由getObject 方法决定的

在这里插入图片描述

总结

  • BeanFactory是个bean 工厂,是一个工厂类(接口), 它负责生产和管理bean的一个工厂,它ioc 容器最底层的接口,是个ioc容器,是spring用来管理和装配普通bean的ioc容器(这些bean成为普通bean)
  • FactoryBean是个bean,在IOC容器的基础上给Bean的实现加上了一个简单工厂模式和装饰模式,是一个可以生产对象和装饰对象的工厂bean,由spring管理后,生产的对象是由getObject()方法决定的(从容器中获取到的对象不是"FactoryBeanTest" 对象)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值