0%

spring源码阅读小结

Bean的生命周期(创建一个Bean的过程):

  1. 解析配置文件得到BeanDefinition并注册BeanDefinition。
    根据传入的信息来解析生成BeanDefinition,如果是注解的形式的话,就是解析注解上的信息,如果是配置文件形式的话,ResourceLoader会根据传入的location来去使用不同的Resource接口的实现类来完成对配置文件的加载和解析,这是策略模式的一个应用。 解析之后得到了一个< beanName, beanDefinition >的一个KV对,然后将其注册到底层容器中,其实就是把它们存到一个Map中,底层容器叫DefaultListableBeanFactory.
  1. 根据BeanDefinition来创建Bean。对于单例非延迟加载的那些bean,会在顶层ApplicaitonContext的构造方法的refrush方法中,被创建出来,并保存到三级缓存中。 创建Bean的流程是:
    1. 如果是单例bean的话,先尝试从缓存中取,如果没取到或者不是单例bean的话,就根据bean的生命周期来调用不同的创建方法
    2. 除去判断循环依赖和后置处理器的回调这类逻辑之外,创建bean的核心就是:
      1. 先进行bean的实例化
      2. 然后进行属性的填充(例如处理Autowired和Value注解)
      3. 调用bean的初始化方法:
        • 调用初始化方法中,会先回调Aware接口
        • 然后回调postBeforeXXX
        • 执行初始化
        • 回调postAfterXXX(在这儿进行AOP)

AOP原理:

  1. @EnableAspectJAutoProxy这个注解的作用:

    1. 设置动态代理方式
    2. 注册AspectJAutoProxyRegistrar:
  2. 利用AspectJAutoProxyRegistrar,
    给容器中注册一个AnnotationAwareAspectJAutoProxyCreator;

  3. AnnotationAwareAspectJAutoProxyCreator实现了
    BeanPostProcessor接口,因此,当Spring加载这个Bean会
    在实例化前调用其后置处理器实现增强

  4. 增强的地方有2个:

    • 一个是在getEarlyBeanReference那边,

    • 一个是在postAfterInitialization那边,

      之所以在两个地方是因为,当单例Bean需要被动态代理但也出现了循环依赖的时候,就需要将这个Bean给提前暴露在外面,而暴露的这个Bean将作为实例保存到其他实例的属性中, 而aop的动态代理,cglib方式实质上是创建了一个新的实例,因此,为了保证注入到其他Bean里的实例依然是被代理的对象,那么就必须在将该实例暴露在外面之前就使用动态代理,

      Spring一个巧妙的地方就是,将第三级的缓存设置成一个接口函数,通过get方法来获取
      Bean实例,之所以这么做是因为要配合getEarlyBeanReference来实现对创建的Bean的一个扩展,所以,如果一个单例Bean满足循环依赖的条件,并且需要进行aop,那么就会在
      getEarlyBeanReference这里尝试进行动态代理。

      而对于没有发生循环依赖的那些bean来说,如果需要进行aop,那么它们实际上实在postAfterInitialization那边进行动态代理的。并且在这边进行代理之前,会先判断这个被代理的bean是否被暴露在外面(暴露在外面的bean都存在一个集合中,看这个bean是否在这个集合中就能判断这个bean是否暴露在外面),只有这个bean没有暴露在外面,才能够在这里尝试进行动态代理.

      进行动态代理的入口是调用一个叫wrapIfNecessary的类的,它会先获取作用在当前Bean上的所有切面,并根据Order进行排序,然后再根据EnableAutoProxy标签里的参数来决定是使用cglib来做还是使用jdk proxy来做,当然,如果使用jdk proxy但被代理对象没有实现接口的话,依然是使用cglib来做.

IOC原理的理解

IOC的实现原理,我认为主要就是通过实现IOC容器来对Bean进行一个管理.

而对Bean的管理,就是Bean的注册和创建,使得之后能够通过beanName获取到自己需要的bean

Bean的注册过程主要就是通过解析配置文件或注解来得到 < beanName, BeanDefinition > 的KV对,然后保存到底层容器中,而Bean的创建过程,主要做的工作就是:一个是bean的合法性检查,就是判断是否出现循环依赖等问题,一个是后置处理器的回调,这一回调出现在Bean真正创建时的各个时期(比如实例化的前后,初始化的前后等),还有一个就是对Bean的真正创建,而对bean真正创建的过程又主要分为3步:

  • 第一步是实例化:就是使用合适的构造器或其他方法来实例化bean,
  • 第二步是类型填充主要做的工作就是完成对Autowied,Value这一注解的完成,
  • 第三步是初始化主要做的工作是对Aware接口的回调和初始化方法的调用.

读Spring源码学习到的设计模式:

1. 单例(使用:BeanFactory)

双重锁校验 / 静态内部类 / 枚举

2. 工厂方法

简单工厂方法

根据输入来返回需要创建的对象

工厂模式

工厂模式就是通过继承工厂接口来实现对对象的创建,每一个子类工厂用于创建一种类型的对象

抽象工厂模式

抽象工厂模式就是,一个子类工厂用于创建一种类型的多种对象,举个例子来说的话,如果使用工厂模式来创建鼠标,那么对于创建苹果牌的鼠标,创建苹果牌的键盘,创建华为牌的鼠标都是独立的一个工厂,而对于抽象工厂模式,会有一个创建苹果牌系列产品的工厂,它可以生产苹果牌鼠标,苹果牌键盘,等等..

3. 委派

用的很多,在applicationcontext顶层容器里,使用:BeanDefinition注册

4. 责任链

BeanPostProcessor里用到、AOP里切面类的调用时使用到

5. 模板模式

源码:refresh里的一些方法是抽象的留给子类去实现

6. 策略模式

策略模式在使用配置文件的形式来配置bean的时候,ResourceLoader会根据输入的不同location信息,来使用不同的策略来加载并解析配置文件,其实就是使用不同的实现了Resource接口的类)

发布-订阅,单一责任原则,接口分离原则,依赖倒置原则,开放封闭原则等