一、問題展現
項目都正常開發,突然有一天,發現某個同僚寫的contoller層注入service為null,但是部分controller又是正常的。并且有時候還會存在通過postman調用controller正常注入service,其他系統通過httpClient調用controller不能正常注入service。
二、問題調查
1、使用postman調用其他的controllerA 發現正常, 并且把同樣的service注入到controllerA 正常注入 沒有任何問題。
有個小插曲,中間還在spring-boot啟動項上 列印出所有的bean 看看是否有兩個對應的controllerW bean注入 然并沒有
ApplicationContext ctx =SpringApplication.run(App.class, args);
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
java.util.Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
2、比較正常controllerA 與 不正常的controllerW 發現沒有什麼本質的差別,代碼也基本上沒有什麼變動。 詭異中...
3、斷點 分析 比較發現 不正常的controllerW 有個詭異問題,enhancerbyspringcglib 這時候真相已經隐藏在圖中了 隻是笨拙的我沒有發現問題~@@~
不正常圖1

正常圖2
4、差別在哪裡 在哪裡, enhancerbyspringcglib 網上搜尋關鍵詞 enhancerbyspringcglib
得到如下資料 a、https://blog.csdn.net/itrider/article/details/43634941
b、http://jinnianshilongnian.iteye.com/blog/1508018
c、http://jinnianshilongnian.iteye.com/blog/1508018
深入 Spring Boot:排查 @Transactional 引起的 NullPointerException
d、http://www.sohu.com/a/216425181_355142
5、整理了一下cglib代理 與 jdk動态代理的差別 等 controllerW上注入的service上确實有使用到注解
@Transactional(rollbackFor = PicaException.class) 以為如獲至寶 然并暖用,隻能說明是可能一個點 但肯定不 是這個問題引起的 因為controllerA 注入同樣的service 沒有問題的
6、 同時把所有的service中使用@Transactional 注解暫時注釋掉 問題沒有得到解決, 但是發現一個現象 這時候service 注入的方式改變了 如下圖
這個現象暫時 不影響正常使用 可以暫時過一下 但 是不是跟controllerW 注入方式一樣呢? 很像吧 這時候陷入死胡同 為什麼??
7、陷入死胡同,這時候隻能判斷這個問題 controllerW的寫法有問題,肯定做了什麼見不得人的操作, 隻能來代碼比較 代碼比較,詢問當事人, 當事人回答,之前哪個日期點的代碼是好的, 好好, 那就一點點代碼回退,一點點代碼比較, 問題終于重制了, 可以正常運作的代碼 與 有問題的代碼的時間節點 内容差異, 發現controllerW 方法體上用了 private修飾 再看一下其他 都是public 果斷重制用public試一下 ok 問題得到解決
8、查找資料
a、https://blog.csdn.net/weixin_41633157/article/details/80083636
原因分析:
容器掃描bean生成代理類的時候,public和protected方法可以被正常代理,而private方法的不會被代理,屬性的注入也是在代理類中完成,是以public/protected方法擷取的注入屬性是完成注入的屬性,private方法擷取的是未完成注入時的屬性,是以是null
9、問題得到解決 但是走了不少彎路。
三、 總結
1、解決問題過程中,心态不夠好,有點急躁
2、準确定位搜尋關鍵詞 這是個提煉能力的問題點。 如果直接搜尋 “controller 方法private 導緻注解丢失“ 明顯很直接得 到答案
3、對spring bean注入 了解不到位。