0%

Spring-源码总结

Spring IOC

  • IOC:控制反转,传统使用对象的时候,对象时由使用者控制的,有了Spring之后,可以将整个对象交给容器来帮我们进行管理

  • DI:依赖注入,将对象的属性注入到具体的对象中,通过@Autowired、@Resource、populateBean方法来完成注入

  • 容器:负责存储对象,使用map结构存储对象,在Spring中存储对象的时候一般有三级缓存:

    SingletonObjects存放完整对象、earlySingtonObjects存放半成品对象,SingletonFactory用来存放lambda表达式和对象名称的映射,整个bean的生命周期,从创建到使用到销毁,各个环节都是容器帮我们控制的。

  • Spring中所有bean都是通过反射生成的,constructor,newInstance,在整个流程中还包含很多扩展点,比如有两个非常重要的接口,BeanFactoryProcessor,BeanPostProcessor,用来实现扩展功能,aop就是在ioc基础之上的一个扩展实现,是通过BeanPostProcessor实现的,Ioc中除了创建对象之后还有一个重点的点就是填充属性

Springbean的生命周期

Spring容器来帮我们控制对象,从对象的产生到销毁的环节都是由容器来控制的

  • 实例化Bean对象,通过反射的方式来生成,在源码中有一个createBeanInstance的方法是专门来生成对象的

  • 当bean对象创建完成之后,对象的属性值都是默认值,所有要开始给bean填充属性,通过populateBean方法来完成对象属性的填充,这中间会涉及到循环依赖

  • 向bean对象中设置容器属性,调用invokerAwareMethods方法来将容器对象设置到具体的bean对象中

  • 调用BeanPostProcessor中的前置处理方法来进行bean对象的扩展工作,ApplicationContextPostProcessor,EmbeddValueResolver等对象

  • 调用invokerInitMethods方法来完成初始化方法的调用,在此方法处理过程中,需要判断当前bean对象是否实现了InitializingBean接口,如果实现了调用afterPropertiesSet方法来最后设置Bean对象

  • 调用BeanPostProcessor的后置处理方法,完成对Bean对象的后置处理工作,aop就是在此处实现的,实现的接口实现名字:AbstractAutoProxyCreator

  • 获取到完整对象,通过getBean的方式去进行对象的获取和使用

  • 当对象使用完成后,容器在关闭的时候,会销毁对象,首先判断是否实现了DispossableBean接口,然后去调用destoryBeanMethord方法

image

BeanFactory和FactoryBean的区别

BeanFactory和FactoryBean都可以用来创建对象,只不过创建的流程和方式不同

  • 当使用BeanFactory的时候,必须要严格遵守bean的生命周期,经过一系列繁杂的步骤之后才可以创建出单例的对象,是流水线式的创建过程

  • FactoryBean是用户可以自定义bean对象的创建流程,不需要按照bean的生命周期来创建,在此接口中包含三个方法:

    • isSingleton:判断是否是单例对象
    • getObjectType:获取对象的类型
    • getObject:在此方法中可以自己创建对象,使用new的方式或者使用代理方式都可以,用户可以按照自己的需要随意去创建对象,在很多框架集成的时候都会实现factoryBean接口,比如Feign

Spring中使用到的设计模式

  • 单例模式:Spring中bean都是单例的

  • 工厂模式:BeanFactory

  • 模板方法模式:postProcessorBeanFactory、各种template

  • 观察者模式:listener、event、multicast

  • 适配器模式:Adapter

  • 装饰者模式:BeanWrapper

  • 责任链模式:aop中会使用一个责任链模式

  • 代理模式:aop动态代理

  • 策略模式:xmlBeanDefinitionReader、PropertiesBeanDefinitionReader

ApplicationContext和BeanFactory的区别

BeanFactory是访问Spring容器的根接口,里面只是提供了某些基本方法的约束和规范

ApplicationContext,为了满足更多需求,ApplicationContext实现了BeanFactory接口,并在此接口的基础之上做了一些扩展功能,提供了更丰富的api调用

一般我们在使用的时候用ApplicationContext更多

Spring如何解决循环依赖

Spring的bean对象的创建都要经历实例化和初始化(属性填充)的过程,通过将对象的状态分开,存在半成品和成品对象的方式来分别进行初始化和实例化;

成品和半成品在存储的时候需要分不同的缓存来进行存储

缓存存储在DefaultSingletonBeanRegistry

只有一级缓存是否可行?(一级缓存:singletonObjects)

不行,会把成品状态的bean对象和半成品状态的bean对象放在一起,而半成品对象时无法暴露给外部使用的

所以,一级缓存放成品,二级缓存放半成品

只有二级缓存行不行?(二级缓存:earlySingletonObjects)

如果整个应用程序中不设计aop的存在,那么二级缓存足以解决循环依赖问题,如果aop中存在循环依赖,那么久必须使用三级缓存

为什么需要三级缓存?(三级缓存:singletonFactoryies)

三级缓存的value类型是ObjectFactory,是一个函数表达式接口,不是直接进行调用的,只有在调用getObject方法的时候才会去调用里面存储的lambda表达式,存在的意义是

保证在整个容器的运行过程中同名的bean对象只有一个

如果一个对象被代理,或者需要生成代理对象,那么要不要生成一个原始对象?要

当创建出代理对象之后,会同时存在代理对象和普通对象,那么此时该选用哪一个?

当需要代理对象的时候,或者代理对象生成的时候必须要覆盖原始对象,也就是说整个容器中有且仅有一个bean对象

在实际调用过程中,是没有办法来确定什么时候对象需要被调用的,因此当某一个对象被调用的时候,优先判断当前对象是否需要被代理,类似于回调机制,当获取对象之后根据传入的lambda表达式来确定返回的是哪一个确定的对象,如果条件符合,返回代理对象,如果不符合则返回原始对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/** 
* 一级缓存,用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用
*
* Cache of singleton objects: bean name to bean instance.
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);


/**
* 二级缓存,提前曝光的单例对象的cache,存放原始的 <beanName,bean> 对象(尚未填充属性),用于解决循环依赖
* 一旦从3级缓存放入这层,就可以被getBean方法查询到,方便进行循环依赖检测
*
*Cache of early singleton objects: bean name to bean instance.
*/
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

/**
* 三级缓存,单例对象工厂的cache,存放 beanName和创建Bean的工厂关系,用于解决循环依赖
*
* Cache of singleton factories: bean name to ObjectFactory.
*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);