Discuss / 手写Spring / BeanPostProcessor的逻辑

BeanPostProcessor的逻辑

Topic source

以文中举例UserServiceProxy的创建流程疏理下BeanPostProcessor的逻辑

1,假设全是字段注入方式

  •  创建名为creatProxy的BeanPostProcessor类型的Bean实例

  • 创建普通Bean实例:mvcController、jdbcTemplate、userService。不分顺序

  • 上述构造器创建userService实例后,循环执行BeanPostProcessor类型列表并执行BeanPostProcessor.postProcessBeforeInitialization时: 通过new的方式创建了userService的代理类userServiceProxy, 在BeanPostProcessor中缓存原实例,并放入了userService的BeanDefinition

  • Bean的实例创建完成,开始Set和字段的依赖注入 injectBean(def)

  • mvcController的userService属性注入了实例userServiceProxy

  • 名称为userService的BeanDefinition在依赖注入时,循环执行BeanPostProcessor类型列表并执行BeanPostProcessor.postProcessOnSetProperty时找到原userService实例,在userService实例上注入了jdbcTemplate

注:虽然有两个实例userService以及userServiceProxy, 但只有一个由IOC容器管理的名称为userService的BeanDefinition

2,假设全是构造方法注入方式

  • 创建名为creatProxy的BeanPostProcessor类型的Bean实例
  • 创建普通Bean实例mvcController: 递归创建userService实例: 在递归创建jdbcTemplate实例
  • jdbcTemplate实例创建完成
  • 依赖jdbcTemplate实例的userService实例创建完成。循环执行BeanPostProcessor类型列表并执行BeanPostProcessor.postProcessBeforeInitialization时: 通过new的方式创建了userService的代理类userServiceProxy, 在BeanPostProcessor中缓存原实例,并放入了userService的BeanDefinition
  • 依赖userService的mvcController创建完成,注入的是userServiceProxy
  • Bean的实例创建完成,开始Set和字段的依赖注入 injectBean(def)
  • 构造方法注入,除上述出现的没有额外的字段需要注入,结束。

证明了两种方式最终的注入逻辑都是文中展示的结构建立依赖关系。注意和Spring真实处理时的逻辑可能会有不同,文种偏重与代理的实现,而且业务代码必须缓存原实例。

似乎Spring在完成了对原实例的依赖注入后才调用BeanPostProcessor对原实例进行处理,因此没有在BeanPostProcessor中保存原实例这样的操作。不过Spring的初始化流程更加复杂,这里的初始化流程更加简洁清晰,缓存实例的解决方式也易于理解。


  • 1

Reply