天天看點

controller層注入service為null,service使用Transactional注解 導緻enhancerbyspringcglib問題

一、問題展現

      項目都正常開發,突然有一天,發現某個同僚寫的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

controller層注入service為null,service使用Transactional注解 導緻enhancerbyspringcglib問題

    正常圖2

controller層注入service為null,service使用Transactional注解 導緻enhancerbyspringcglib問題

    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 注入的方式改變了   如下圖

controller層注入service為null,service使用Transactional注解 導緻enhancerbyspringcglib問題

這個現象暫時 不影響正常使用    可以暫時過一下   但   是不是跟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注入 了解不到位。