记录一次升级公司框架导致的service注入失败的问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/afsvsv/article/details/84437695

背景:公司使用的还是jdk7,早就想升级到jdk8,但是很坑爹的是,公司的框架使用的是Netty3.2.7和spring3.x,不能升级,jdk8必须使用spring4.x才可以,当然,spring4.x可以向下兼容jdk7.思考再三,长痛不如短痛,升级Netty3.2.7到Netty4.1.31(Netty最新版本是5.x但是废弃了,不建议使用),spring3.x升级到spring4.3.20,这样就可以升级到jdk8了

Netty4.x居然不兼容Netty3.x,连包名都换了,升级到4.1.31的过程是痛苦的,代码各种红,各种踩坑,这不是本篇重点,后面写博客一遍Netty升级的踩坑记录

问题:升级以后,Controller注入service失败,跟踪发现为null,如下图:

最初猜测是spring没有加载到,因此写了工具类来验证,如下图:

可以看到,的确是拿到了注入的service,但是为啥是null呢?

难道拿到的controller和当前controller不是同一个嘛?

居然还真不是同一个,那么注入失败,也就找到原因了,下面排查为啥不是同一个controller

跟踪公司框架源码,发现如下代码:

用反射获取的Controller,然后反射调用:

那么问题就在这里了,最初调试的this controller是反射获取的,当然注入失败,无法调用了

尝试解决:

(1)反射获取的bean,如何注入spring bean对象呢?

 先获取spring中的controller,然后,修改调用参数,如下所示:

invokeBizMethod(course,messsage);修改为:

invokeBizMethod((BusinessCourse) ApplicationContextHelper.getBean(ClassUtil.getClassLowerName(course.getClass())), message);

调试发现也不行,因为这个时候Controller不一定被Spring加载到,因为,Spring中加载bean的顺序是不定的,当然,如果能控制Controller的加载顺序先于反射调用的地方,也是可以解决问题的,问题转化为(2)中的bean加载顺序问题。

(2)不用反射拿对象,直接问Spring要

不能框架层反射获取,那么就在项目中直接获取,因为用的是springBoot,没有配置文件,因此笨办法写一个ControllerCollect的辅助类去获取,然后赋值

需要赋值的地方如下:

这样可以解决问题,但是太low了

修改如下:在Controller的基类BaseController中直接获取

然后赋值语句 更新为  httpBizEntry.setCourses(BaseController.courses);

但是这样发现赋值为[],也就是没有赋值成功,分析原因,是spring中bean加载顺序问题。因为赋值的地方也是@Bean注解修饰的,

那么获取coureses的bean必须先于赋值地方的这个bean加载才可以,这样需要解决的就是如何控制spring中bean的加载顺序问题。

Spring中bean的加载顺序,根据需要有明显的加载依赖关系,首先,可以在代码中手动初始化加载,当然这个肯定不会用了,其次考虑用@DependOn注解来控制,但是Controller是多个,只要继承了BaseController的都是,并且需要指定bean name,分析以后,不符合要求。最后,考虑用@Order注解来控制,修改如下:

问题解决,其实如果使用配置文件,直接xml里面配置,就不会出现这个问题,现在虽然解决了问题,但是也需要在代码里面配置,还是不够友好,后面还是需要考虑如何在框架层处理掉,待完善。

猜你喜欢

转载自blog.csdn.net/afsvsv/article/details/84437695
今日推荐