有道无术,术尚可求也!有术无道,止于术!
关于Spring生命周期的学习,前面已经写过不少篇文章去不断的探究Spring对一个Bean的建立、管理过程,在整个SpringBean的生命周期中,BeanPostProcessor
是不可绕过的一环,他几乎贯穿了整个Spring Bean的生命周期!几乎咱们如今所熟知Bean的生命周期的功能,大部分都是由BeanPostProcessor
完成的!好比,依赖注入、循环依赖问题、Aop等,所有都是由BeanPostProcessor
的扩展实现的!java
BeanPostProcessor
的学习是咱们理解Spring如何插手对象实例化的一个重要的转折点!咱们经过BeanPostProcessor
的扩展,可以对Spring作一些很'骚'的操做!web
以往的每一篇文章,对于SpringBean生命周期的介绍,都是从程序扫描开始的,可是事实上,既然是一个Bean的声明周期,那么对于生命周期的理解就要从对象的初始化开始!本篇文章将从头至尾解析Spring BeanPostProcessor整个回调实现!spring
1、寻找合适的构造函数建立对象
java建立对象是基于反射来建立的!反射建立对象也是基于构造函数来建立的!Spring也不可能脱离于java以外,因此spring在建立对象以前必需要作的就是,他要肯定本次建立对象,所须要的构造函数!设计模式
为何须要推断构造函数呢?由于Spring在帮咱们管理bean的时候它并不知道他要使用什么样的构造方法!由于咱们都知道Spring给咱们提供的属性注入里面有一个【构造函数注入】!假设你有两个构造函数,此时Spring就会很混乱,他也不知道应该使用哪种!因此Spring在建立对象以前会使用一个扩展点,去推断出符合Spring条件的构造函数,而后再下面建立对象的时候,选择一个最为合适的构造函数建立对象!缓存

推断构造函数的回调就是经过SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
方法来作的!SmartInstantiationAwareBeanPostProcessor是BeanPostProcessor里面的一个子类,它对原有的接口进行增长,增长determineCandidateConstructors方法,再建立对象以前会回调这个方法,推断出将来建立对象的时候可能要须要的构造方法!事实上!这里也会进行注解@Lookup
的解析,后面的学习也会说到,这里不重点说!微信

Spring默认的实现是: AutowiredAnnotationBeanPostProcessor
app
它是默认寻找加了@Autowired
注解的构造方法,这里就不细说了,后面会有专门的篇章来介绍Spring的构造方法推断!编辑器
咱们本身也能够基于这个扩展点去扩展Spring,使得Spring建立对象前拥有更多的可能性!函数
扩展点:实现AutowiredAnnotationBeanPostProcessor
接口复写determineCandidateConstructors
方法来控制准备使用的构造函数!post
2、解析你的各种Spring注解
java在建立对象完成后,理所应当就是应该去开始向对象注入属性,可是有一点,在注入属性的时候就必需要知道一件事,就是那个属性须要注入!
因此Spring为了方便起见,在注入属性以前我就把你对象里面将来要操做的属性给解析了,而后保存起来,将来进行对象属性注入或其余操做的时候就不须要在进行解析了,直接从缓存中取,也从侧面体现了设计模式中职责单一的特色!

对于@Autowired
,@Value
的解析是由BeanPostProcessor
的子类MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
来作的!
在建立完成对象以后,填充对象以前会 进行这一步操做,Spring内置了一个AutowiredAnnotationBeanPostProcessor
的实现,他的主要做用是用于解析注解@Value、@Autowired
等注解,将对应的属性或者方法和其对应的注解属性包装成一个对象,缓存起来,以便于在填充属性的时候,直接进行从缓存获取进行属性的填充!
扩展点:实现MergedBeanDefinitionPostProcessor
接口复写postProcessMergedBeanDefinition
方法来控制一些特殊注解的解析!
3、循环依赖中三级缓存的精髓
属性和方法解析完成以后,此时就应该开始注入属性了,在注入属性以前须要保存一个工厂对象,基于这个工厂对象可以返回一个bean对象!为何要保存工厂对象呢?还记得Spring为了解决循环依赖中的代理问题,就建立了一个三级缓存,里面主要存放为了生成代理对象的工厂对象,这第三次回调就是这个代理对象生成器!
上期Spring三级缓存的问题说的很明白,这里为何会放一个工厂,这里不作太多的赘述!可是,工厂对象里面是如何生成一个代理对象呢?
他是基于SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
的方法来解决代理逻辑的!假设对象发生了循环依赖,就会经过工厂调用这个方法,最终完成AOP的逻辑!

须要注意的是,这里仅仅是设置了一个代理逻辑,并无真正的调用,这个在整个Spring解决循环依赖中说的很明白!他的调用时机是在被依赖的时候,这里不作赘述!
4、你的自动注入生不生效我说的算
在对象初始化以后,属性注入以前,会进行一次属性是被可以被注入的回调,该回调会返回一个布尔类型的返回值来验证最终属性是否生效!
该方法最终会回调InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
方法,该方法的定义以下:

扩展点:实现InstantiationAwareBeanPostProcessor
接口复写postProcessAfterInstantiation
方法来控制这个类到底需不须要自动注入!
5、属性填充
属性填充是基于后置处理器来作的,这里会会寻找(二)中寻找到的@Value或@Autowirte等属性或者方法,进行对应数据的注入!
Spring自动注入属性的时候会回调,InstantiationAwareBeanPostProcessor#postProcessProperties
回调,完成最后的属性注入!所注入的标识就是在第二步寻找到的字段和方法,经过反射进行操做!

经过实现InstantiationAwareBeanPostProcessor
重写postProcessProperties
方法,能够在某个对象属性注入的时候,就行值得修改操做,能够插手Spring对于值的注入的问题!
和全部的都同样,都是寻找到全部的值,进行循环调用!最后返回属性与值的对应关系以供后续使用!

扩展点:实现InstantiationAwareBeanPostProcessor
接口复写postProcessProperties
方法来控制这个类即将要注入的属性或方法的值!
6、花式Aware接口调用
不知道你是否使用过Spring提供的一些Aware这些额外的扩展接口,不了解的能够去了解一下,灵活使用Aware接口,能够为Spring增长不少意想不到不到的功能,好比一些
SpringUtil
固然大部分是这样命名的,就是经过Aware接口来实现的!

扩展点:实现以上三个接口
复写对应的方法
能够获取对应的属性!
7、Spring Bean初始化前,你想干什么?
你想在Spring调用你的初始化方法以前作些什么吗?Spring固然为你提供了修改的可能性!
Spring在bean初始化前会回调【BeanPostProcessor#postProcessBeforeInitialization】方法!

扩展点:实现BeanPostProcessor
复写postProcessBeforeInitialization
方法能够在类初始化以前进行修改bean!
8、你想在Bean被完全建立完成前作些什么吗?
Spring在这一步会回调你的初始化方法,也就是实现了
InitializingBean
接口的afterPropertiesSet
方法

扩展点:实现InitializingBean
复写afterPropertiesSet()方法
可让bean在初始化的时候作些什么!
9、Spring Bean完成初始化后,你想作些什么?
Spring完成了整个Bean的生命周期了,你想在这个时候作些什么吗?还记得Spring Aop吗?他就是在这一步进行完成的!

这一步的调用是Spring生命周期的最后一步,咱们所熟知的AOP 也是在这里进行装载完成的!
扩展点:实现BeanPostProcessor
复写postProcessAfterInitialization()方法
能够修改bean的最终返回实例!
最后,祝你们双节快乐!另外,国庆期间做者就不更新了!我要出去浪一段时间,哈哈!而后做者是个穷屌丝,没钱发红包!告辞!
10、总结
才疏学浅,若是文章中理解有误,欢迎大佬们私聊指正!欢迎关注做者的公众号,一块儿进步,一块儿学习!
❤️「转发」 和 「在看」 ,是对我最大的支持❤️
本文分享自微信公众号 - JAVA程序狗(javacxg)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。