使用公司内部服务框架时,需要在过滤器中引入dao类,进行操作,但是使用注解autowire注入后是null,记录下排查过程
boot版本2.2
cloud版本2011
- 首先在引入dao的类初始化是否报错,即从applicationContext的getBean方法,是否抛出异常
- 检查autowire注解注入依赖bean的逻辑,即当前dao类初始化,postProcessProperties可以看到dao的meta信息,然后执行dao类的初始化
- dao的实例依赖了mybatisProperties,创建实例时,applyBeanPostProcessorsBeforeInitialization调用beanpostprocessors的postProcessBeforeInitialization方法processors是列表,依次调用执行。其中ConfigurationPropertiesBindingPostProcessor执行yml配置文件信息绑定到具体的属性类
- 绑定配置时执行defaultsBindHandlerAdvisor初始化并实例化他的factorybean ,CommonsConfigAutoConfiguration继续执行。postProcessBeforeInitialization里面初始化自定义的properties,此时又触发了属性绑定执行,最后报错
Could not bind properties to 'xxxClientConfigurationProperties' : prefix=xxx.client, ignoreInvalidFields=false, ignoreUnknownFields=true;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'defaultsBindHandlerAdvisor': Requested bean is currently in creation: Is there an unresolvable circular reference?
结论:在初始化实例过程中,属性绑定的执行触发了循环依赖。
排查过程总结
- beanpostprocessor类不熟悉,完全没想到dao的初始化关系到一整个属性配置的加载
- 思路问题:因为不熟悉就瞎猜,瞎猜就会绕远路,一个头两个大,不能冷静分析,无法直达问题核心
- 循环依赖:网上有搜索的很多循环依赖的解决方法,比如set方法注入,修改processor的顺序等等,这里核心是属性绑定的问题,这些方法下面继续分析
- 解决方法:内部框架使用的版本与boot和cloud版本一致,虽然改个版本号可以解决问题,但是的更重要的是问题的排查过程和对于spring容器初始化的理解不够。还有个遗留点,修改版本后不报错,那么低版本的初始化过程和高版本有什么区别呢,继续分析