BeanPostProcessor对类的实例化顺序的影响——@Value失效

一、背景

springboot1.5.9集成JavaMelody的时候, https://github.com/javamelody/javamelody/blob/without-spring-boot-starter/javamelody-for-spring-boot/src/main/java/hello/JavaMelodyConfiguration.java#L110 发现这种集成方式的配置采用的硬编码方式,不能根据配置文件进行配置。因此我就想将配置方式修改为从配置文件读取,我的第一想法是采用@Value注解,先把一个log参数读取进来,但是发现该参数一直不能生效。

第一步,将monitoringFilter以下的bean都注释掉,该配置就生效了。

第二步,逐步增加注释掉的bean,当去掉SpringDataSourceBeanPostProcessor 和 SpringRestTemplateBeanPostProcessor这两个bean的加载,log参数就加载进来了。

那是什么原因呢?

二、原因探析

2.1 表象的深入分析

1.经过查看源码发现,SpringDataSourceBeanPostProcessor和SpringRestTemplateBeanPostProcessor实现了BeanPostProcessor, PriorityOrdered这两个接口。

2.然后我就把这种实现方式抽离出来简化了数据结构和实现方便调试,代码在这里

经过调试发现 实现了BeanPostProcessor, PriorityOrdered这两个接口的bean影响@Value的bean的加载。

注意: @Value的实现类AutowiredAnnotationBeanPostProcessor也实现了BeanPostProcessor, PriorityOrdered这两个接口。

而且,还多打出来一行信息:

020-08-08 20:50:32.412  INFO 2700 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'myConfiguration1' of type [com.example.issue.MyConfiguration1$$EnhancerBySpringCGLIB$$ed2d2a7f] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

据此推断,可能是MyConfiguration1启动时机过早,导致实现@Value注解的AutowiredAnnotationBeanPostProcessor没来得及实例化及注册呢。

2.2 BeanPostProcessor启动阶段对其依赖的Bean造成的影响

BeanPostProcessor的启动阶段包括四个阶段

  • 第一阶段applicationContext内置阶段
  • 第二阶段priorityOrdered阶段
  • 第三阶段Ordered阶段
  • 第四阶段nonOrdered阶段

第一阶段的代码在AbstractApplicationContext.refresh()的 prepareBeanFactory()方法里,这里就不展示代码了。

第二阶段到第四阶段实例化和注册过程如下:

// 启动 Spring 应用上下文
AbstractApplicationContext.refresh()
//注册BeanPostProcessors
-> AbstractApplicationContext.registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)
//调用委托执行post processors任务的工具类PostProcessorRegistrationDelegate去执行注册逻辑
-> PostProcessorRegistrationDelegate.registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext)

然后分成三个阶段依次实例化并注册实现了PriorityOrdered的BeanPostProcessor、实现了Ordered的BeanPostProcessor、普通的BeanPostProcessor(没实现Ordered),代码如下:

	// Separate between BeanPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>()</
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值