Bean的生命周期(创建一个Bean的过程):
- 解析配置文件得到BeanDefinition并注册BeanDefinition。
根据传入的信息来解析生成BeanDefinition,如果是注解的形式的话,就是解析注解上的信息,如果是配置文件形式的话,ResourceLoader会根据传入的location来去使用不同的Resource接口的实现类来完成对配置文件的加载和解析,这是策略模式的一个应用。 解析之后得到了一个< beanName, beanDefinition >的一个KV对,然后将其注册到底层容器中,其实就是把它们存到一个Map中,底层容器叫DefaultListableBeanFactory.
- 根据BeanDefinition来创建Bean。对于单例非延迟加载的那些bean,会在顶层ApplicaitonContext的构造方法的refrush方法中,被创建出来,并保存到三级缓存中。 创建Bean的流程是:
- 如果是单例bean的话,先尝试从缓存中取,如果没取到或者不是单例bean的话,就根据bean的生命周期来调用不同的创建方法
- 除去判断循环依赖和后置处理器的回调这类逻辑之外,创建bean的核心就是:
- 先进行bean的实例化
- 然后进行属性的填充(例如处理Autowired和Value注解)
- 调用bean的初始化方法:
- 调用初始化方法中,会先回调Aware接口
- 然后回调postBeforeXXX
- 执行初始化
- 回调postAfterXXX(在这儿进行AOP)
AOP原理:
@EnableAspectJAutoProxy这个注解的作用:
- 设置动态代理方式
- 注册AspectJAutoProxyRegistrar:
利用AspectJAutoProxyRegistrar,
给容器中注册一个AnnotationAwareAspectJAutoProxyCreator;AnnotationAwareAspectJAutoProxyCreator实现了
BeanPostProcessor接口,因此,当Spring加载这个Bean会
在实例化前调用其后置处理器实现增强增强的地方有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接口的类)
发布-订阅,单一责任原则,接口分离原则,依赖倒置原则,开放封闭原则等