关于Spring生命周期的学习,前面已经写过很多篇文章去不断的探究Spring对一个Bean的创建、管理过程,在整个SpringBean的生命周期中,BeanPostProcessor是不可绕过的一环,他几乎贯穿了整个Spring Bean的生命周期!几乎我们现在所熟知Bean的生命周期的功能,大部分都是由BeanPostProcessor完成的!比如,依赖注入、循环依赖问题、Aop等,全部都是由BeanPostProcessor的扩展实现的!

BeanPostProcessor的学习是我们理解Spring如何插手对象实例化的一个重要的转折点!我们通过BeanPostProcessor的扩展,能够对Spring做一些很’骚’的操作!

以往的每一篇文章,对于SpringBean生命周期的介绍,都是从程序扫描开始的,但是事实上,既然是一个Bean的声明周期,那么对于生命周期的理解就要从对象的初始化开始!本篇文章将从头到尾解析Spring BeanPostProcessor整个回调实现!

一、寻找合适的构造函数创建对象

java创建对象是基于反射来创建的!反射创建对象也是基于构造函数来创建的!Spring也不可能脱离于java之外,所以spring在创建对象之前必须要做的就是,他要确定本次创建对象,所需要的构造函数!

为什么需要推断构造函数呢? 因为Spring在帮我们管理bean的时候它并不知道他要使用什么样的构造方法!因为我们都知道Spring给我们提供的属性注入里面有一个【构造函数注入】!假设你有两个构造函数,此时Spring就会很混乱,他也不知道应该使用哪一种!所以Spring在创建对象之前会使用一个扩展点,去推断出符合Spring条件的构造函数,然后再下面创建对象的时候,选择一个最为合适的构造函数创建对象!

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

Spring默认的实现是: AutowiredAnnotationBeanPostProcessor

它是默认寻找加了@Autowired注解的构造方法,这里就不细说了,后面会有专门的篇章来介绍Spring的构造方法推断!

我们自己也可以基于这个扩展点去扩展Spring,使得Spring再创建对象前拥有更多的可能性!

扩展点:实现AutowiredAnnotationBeanPostProcessor接口复写determineCandidateConstructors方法来控制准备使用的构造函数!

二、解析你的各类Spring注解

java在创建对象完成后,理所应当就是应该去开始向对象注入属性,但是有一点,在注入属性的时候就必须要知道一件事,就是那个属性需要注入!

所以Spring为了方便起见,在注入属性之前我就把你对象里面未来要操作的属性给解析了,然后保存起来,未来进行对象属性注入或其他操作的时候就不需要在进行解析了,直接从缓存中取,也从测面体现了设计模式中职责单一的特点!

对于@Autowired,@Value的解析是由BeanPostProcessor的子类MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition来做的!

在创建完成对象之后,填充对象之前会 进行这一步操作,Spring内置了一个AutowiredAnnotationBeanPostProcessor的实现,他的主要作用是用于解析注解@Value、@Autowired等注解,将对应的属性或者方法和其对应的注解属性包装成一个对象,缓存起来,以便于在填充属性的时候,直接进行从缓存获取进行属性的填充!

扩展点:实现MergedBeanDefinitionPostProcessor接口复写postProcessMergedBeanDefinition方法来控制一些特殊注解的解析!

三、循环依赖中三级缓存的精髓

属性和方法解析完成之后,此时就应该开始注入属性了,在注入属性之前需要保存一个工厂对象,基于这个工厂对象能够返回一个bean对象!为什么要保存工厂对象呢?还记得Spring为了解决循环依赖中的代理问题,就创建了一个三级缓存,里面主要存放为了生成代理对象的工厂对象,这第三次回调就是这个代理对象生成器!

上期Spring三级缓存的问题说的很明白,这里为什么会放一个工厂,这里不做太多的赘述!但是,工厂对象里面是如何生成一个代理对象呢?

他是基于SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference的方法来解决代理逻辑的!假设对象发生了循环依赖,就会通过工厂调用这个方法,最终完成AOP的逻辑!

需要注意的是,这里仅仅是设置了一个代理逻辑,并没有真正的调用,这个在整个Spring解决循环依赖中说的很明白!他的调用时机是在被依赖的时候,这里不做赘述!

四、你的自动注入生不生效我说的算

在对象初始化之后,属性注入之前,会进行一次属性是被能够被注入的回调,该胡回调会返回一个布尔类型的返回值来验证最终属性是否生效!

该方法最终会回调InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法,该方法的定义如下:

扩展点:实现InstantiationAwareBeanPostProcessor接口复写postProcessAfterInstantiation方法来控制这个类到底需不需要自动注入!

五、属性填充

属性填充是基于后置处理器来做的,这里会会寻找(二)中寻找到的@Value或@Autowirte等属性或者方法,进行对应数据的注入!

Spring自动注入属性的时候会回调,InstantiationAwareBeanPostProcessor#postProcessProperties回调,完成最后的属性注入!所注入的标识就是在第二步寻找到的字段和方法,通过反射进行操作!

通过实现InstantiationAwareBeanPostProcessor重写postProcessProperties方法,可以在某个对象属性注入的时候,就行值得修改操作,可以插手Spring对于值的注入的问题!

和所有的都一样,都是寻找到所有的值,进行循环调用!最后返回属性与值的对应关系以供后续使用!

扩展点:实现InstantiationAwareBeanPostProcessor接口复写postProcessProperties方法来控制这个类即将要注入的属性或方法的值!

六、花式Aware接口调用

不知道你是否使用过Spring提供的一些Aware这些额外的扩展接口,不了解的可以去了解一下,灵活使用Aware接口,可以为Spring增加很多意想不到不到的功能,比如一些SpringUtil当然大部分是这样命名的,就是通过Aware接口来实现的!

扩展点:实现以上三个接口复写对应的方法可以获取对应的属性!

七、Spring Bean初始化前,你想干什么?

你想在Spring回调你的初始化方法之前做些什么吗? Spring当然为你提供了修改的可能性!

Spring在bean初始化前会回调【BeanPostProcessor#postProcessBeforeInitialization】方法!

扩展点:实现BeanPostProcessor复写postProcessBeforeInitialization方法可以在类初始化之前进行修改bean!

八、你想在Bean被彻底创建完成前做些什么吗?

Spring在这一步会回调你的初始化方法,也就是实现了InitializingBean接口的afterPropertiesSet方法

扩展点:实现InitializingBean复写afterPropertiesSet()方法可以让bean在初始化的时候做些什么!

九、Spring Bean完成初始化后,你想做些什么?

Spring完成了整个Bean的生命周期了,你想在这个时候做些什么吗?还记得Spring Aop吗?他就是在这一步进行完成的!

这一步的调用是Spring生命周期的最后一步,我们所熟知的AOP 也是在这里进行装载完成的!

扩展点:实现BeanPostProcessor复写postProcessAfterInitialization()方法可以修改bean的最终返回实例!

十、总结

最后,祝大家双节快乐!另外,国庆期间作者就不更新了!我要出去浪一段时间,哈哈!然后作者是个穷屌丝,没钱发红包!告辞!

才疏学浅,如果文章中理解有误,欢迎大佬们私聊指正!欢迎关注作者的公众号,一起进步,一起学习!

一个Spring Bean从诞生到逝去的九次人生转折!相关推荐

  1. 你还在问我Bean的生命周期?带你看看一个Spring Bean从诞生到逝去的九次人生转折!

    前言 关于Spring生命周期的学习,前面已经写过很多篇文章去不断的探究Spring对一个Bean的创建.管理过程,在整个SpringBean的生命周期中,BeanPostProcessor是不可绕过 ...

  2. coherence安装_在Oracle Coherence中分发Spring Bean

    coherence安装 本文展示了如何通过使用Oracle Coherence中的EntryProcessor和可移植对象格式(POF)功能来分发Spring Bean. Coherence通过Ent ...

  3. 在Oracle Coherence中分发Spring Bean

    本文展示了如何通过使用Oracle Coherence中的EntryProcessor和可移植对象格式(POF)功能来分发Spring Bean. Coherence通过EntryProcessor ...

  4. 想减少代码量,快设置一个有感知的 Aware Spring Bean

    本文分享自华为云社区<有感知的 Aware Spring Bean>,作者:陈皮的JavaLib. 有感知能力的 Spring Bean 正常情况下,Spring 中的 Bean 对 Sp ...

  5. @bean 什么时候执行_写好一个Spring组件的实现步骤是什么?

    这篇文章主要介绍了如何写好一个Spring组件的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,希望可以帮助到大家! 本文详细的介绍了Spring组件的实现步骤, ...

  6. 今天出现一个Spring无法向Service里面注入bean的异常

    今天出现一个Spring无法向某个Service里面注入另外一个Service的异常,后来检查过了才发现是因为这个被注入Service,里面注入了自身,特此记录一下. 转载于:https://www. ...

  7. spring Bean自动装配

    spring Bean自动装配 自动装配是使用spring满足bean依赖的一种方式. spring会在应用上下文中为某个bean寻找其依赖的bean. spring自动装配需要从两个角度来实现,或者 ...

  8. 第一个spring程序

    第一个spring程序: 第一步:导入jar包. 新建maven项目: <dependency><groupId>org.springframework</groupId ...

  9. 一起学spring--我的第一个Spring程序,简单粗暴易懂

    欢迎来<一起下spring>系列博文第一篇 一.首先让我们来做一个对比:不使用spring和使用spring的区别 1.首先是不使用spring的情况: 创建一个Student对象,里面只 ...

最新文章

  1. C++ 调用lib 和 dll的 方法 及 动态库DLL与静态库lib的区别
  2. python降级-关于卸载:如何从Python 3.2降级到2.7?
  3. android studio不能更新代码,解决Android Studio 和 Android SDK Manager 无法在线更新的问题....
  4. Centos实现svn本地认证apache认证
  5. autohotkey php,Autohotkey+php实现免浏览器听录音
  6. 【学习笔记】整体二分
  7. golang 结构体断言_Golang中的reflect原理
  8. ASP.NET 文件下载 .
  9. 全网最全Python操作Excel教程,建议收藏!
  10. Visual Studio 2017 15.5 正式发布,性能再提升
  11. [剑指offer] 旋转数组的最小数字
  12. 能不能做好性能测试,要看你有没有性能测试思维
  13. 运维记之源码编译nfs-utils和rpcbind
  14. linux下创建桌面快捷方式,简单快捷(ubuntu)
  15. Syzmlw 蜗居大结局f
  16. 【新手教程】51Sim-One Cloud 2.0如何接入被测算法
  17. workerman wss 配置备忘录
  18. 巧妙使用css美化网页
  19. 【IOT】NB-IOT模块连接Onenet物联网云平台2020年实测
  20. 拉格朗日多项式插值法 思路详解+详细代码

热门文章

  1. Linux下Nuke 12.2.v5 安装及使用
  2. 业务结构单一,天润云能借IPO说出好故事吗?
  3. std::floor和std:ceil简述
  4. P1017 进制转换 (洛谷)
  5. Unity学习日志_Unity地形系统简介
  6. php微信公众号无限制群发,微信公众号无限群发 - viki_php的个人空间 - OSCHINA - 中文开源技术交流社区...
  7. Python爬虫实战 | (3) 爬取豆瓣电影Top250
  8. 爬虫实战1:爬取豆瓣top250电影
  9. html窗口最小宽度和高度,html设置尺寸大小的方法
  10. 红旗linux做成u盘,红旗linux下如何用u盘