作为BAT的java开发者,最近感觉到越来越多的项目开始从ssm框架转向了springboot。
尤其是一些希望将服务拆分做分布式,做微服务的项目,对springboot的需求就更加强烈了。
前段时间,我们项目希望将一个整体服务中一个会频繁改动的子功能拆分出来,这样的好处是以后每次更新子服务,就不用担心线上其他重点服务受到影响了。
这个工作交给了我,在代码拆分部分的工作其实很平淡也很顺利,因为这部分服务本身和其他模块的耦合度就不高,唯一麻烦的就是要把数据库很多张表的操作句柄也要复制过去。
现在问题来了,我们原来使用的是SSM框架,也就是说,我们是通过ApplicationContextAwareListener类实现了ApplicationContextAware接口后,用context提供的getBean函数来拿到数据库的句柄的,如脱敏后的下图。
然而,Springboot框架是不用实现这个接口的,也就是说不存在context以及getBean函数。springboot是通过注解,利用IoC直接能获取数据库句柄的。但是我在数据库相关的文件中增加了@Repository 注解后,发现工程启动后并没有扫描到这个bean。
也就是说,下图中虽然用了autowired注解,但是实际上,springboot并没有扫描到对应的类并加载进容器,在实际使用中下面各个mapper变量会抛空指针异常。
在查询了很多资料之后,终于定位到了问题,原来是这些mapper变量所在的类被设置为了单例模式,这种情况下,就算在class外层增加了component注解,springboot也不会来进行干涉,自然autowired也不会生效了。
解决方式有两种:
1 将private xxxxManager(){supervisor();}部分注释掉,改为{instance=this}即可。
2 再写一个函数,增加postCostruct注解,有了这个注解,就算是单例,实例化之后,springboot也会来执行这个函数,函数内容为xxxMapper=this.xxxMapper; 保证在这个manager实例化之后,这些mapper也能被自动注入句柄对象了。
至此,问题就解决了。
后期感想,无技术内容,不感兴趣的朋友可以退出啦。
这个问题当时困扰了相当一段时间,我在网上找了很多经验,很多东西是在别人的项目中生效,但是到了我这里就是不成立,试了很多种方法都是在抛错,让我感觉陷入迷宫之中一样。
但是在实际工作中,不能因为问题难就停止,其他同事也在忙,我不能仗着自己的性别优势就去无限的打扰别人,经过了99次的失败之后,终于柳暗花明,解决问题,那种如释重负的感觉,真是美妙。但是同时,也让我认识到自己对spring框架相关的知识还是没有完全掌握,这次也算为自己查缺补漏了。