最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring依賴注入成功但在調(diào)用接口的時(shí)候拿到的依賴卻是null問題

 更新時(shí)間:2023年12月14日 09:42:44   作者:不喜歡吃貓的魚  
這篇文章主要介紹了spring依賴注入成功但在調(diào)用接口的時(shí)候拿到的依賴卻是null問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

前言

使用過spring的同學(xué)們都知道,如果出現(xiàn)了依賴注入失敗的問題首先會想到以下幾點(diǎn):

1、對應(yīng)的類有沒有寫@Service或@Component注解以供能被spring掃描注冊;

2、在配置中有沒有配置要掃描的包路徑,或是對應(yīng)的類是否在已配置的包路徑下;

3、配置的包路徑錯(cuò)誤導(dǎo)致掃描失??;

4、同一個(gè)項(xiàng)目中jar沖突導(dǎo)致在注冊bean過程失敗進(jìn)而導(dǎo)致注入不成功;

問題描述

使用springboot的時(shí)候發(fā)現(xiàn)項(xiàng)目正常編譯運(yùn)行,所有的bean都被掃描加載了,但是在前端調(diào)用接口的時(shí)候發(fā)現(xiàn)controller里的service竟然是null。

具體如下圖所示:

具體截圖

由上圖可以看出Device對應(yīng)的那個(gè)bean在spring容器中已經(jīng)是被注冊過了的,就意味著并不是對應(yīng)的類沒有被加載掃描到。

但我通過在測試類中運(yùn)行發(fā)現(xiàn)使用同樣的注入方式是可以注入成功并成功運(yùn)行,如下圖所示:

注入測試

為了進(jìn)一步測試是否能正常的注入依賴,將原先的注入方式改成了構(gòu)造注入的方式,發(fā)現(xiàn)也是能夠正常的注入進(jìn)去,如下圖所示:

通過以上測試發(fā)現(xiàn),這次的問題并不是因?yàn)閽呙杪窂交蚴亲⒔獾膯栴}導(dǎo)致的,當(dāng)然這里的jar依賴這些也是正常的。

分析

仔細(xì)回想下這次的問題,項(xiàng)目服務(wù)能正常啟動,在spring的bean容器中也能找到對應(yīng)的bean那就說明bean注冊過程是沒有問題的。

接下來通過注入測試發(fā)現(xiàn)這幾個(gè)service也是能夠正常的注入到controller里,那說明項(xiàng)目中DI這個(gè)過程也是OK的,否則的話不可能是換一種注入方式就能注入。

由此可見,此問題并不是因?yàn)閟pring的問題導(dǎo)致。接下來本菜鳥又查詢了一些資料說可能是因?yàn)閯討B(tài)代理的問題導(dǎo)致,項(xiàng)目中沒有獨(dú)特申明代理方式所以默認(rèn)使用的是JDK的動態(tài)代理。

轉(zhuǎn)眼一想感覺是發(fā)現(xiàn)什么了(此處省略一萬個(gè)滑稽…),感覺離成功又更近一步了。

這里我們先來看下常用的動態(tài)代理:

1、jdk動態(tài)代理:

  • 使用jdk動態(tài)代理只能對實(shí)現(xiàn)了接口的類生成代理,而不能針對類;
  • 使用反射生成代理類;

2、cglib動態(tài)代理:

  • 使用cglib代理是針對類實(shí)現(xiàn)代理,主要是對指定的類生成一個(gè)子類,覆蓋其中的方法(繼承);
  • 底層采用ASM字節(jié)碼生成框架,使用字節(jié)碼技術(shù)生成代理類,比使用Java反射效率要高。

了解到這里后本菜感覺想到點(diǎn)什么了,本菜的項(xiàng)目中沒有單獨(dú)設(shè)置代理模式,所以spring對bean處理的時(shí)候默認(rèn)是使用了jdk動態(tài)代理,而項(xiàng)目里的service并非是接口而是一個(gè)class,而且還未實(shí)現(xiàn)某個(gè)接口,只是單純的class

?

本菜就想,是不是因?yàn)榻涌谑菃渭兊念悰]有實(shí)現(xiàn)接口,而jdk的動態(tài)代理沒有將這個(gè)類代理到,所以導(dǎo)致注入失敗了,于是本菜就設(shè)置了下代理為cglib動態(tài)代理:

但經(jīng)本菜鳥測試發(fā)現(xiàn),問題依舊存在…(內(nèi)心開始MMP了)。這時(shí)本菜鳥又想起了另一個(gè)點(diǎn),spring在對bean進(jìn)行代理的時(shí)候會自行選擇代理方式:

(1)當(dāng)Bean實(shí)現(xiàn)接口時(shí),Spring就會用JDK的動態(tài)代理;

(2)當(dāng)Bean沒有實(shí)現(xiàn)接口時(shí),Spring就使用CGlib動態(tài)代理;

所以說再次申明代理方式也是沒有用的。

除了以上的一些疑點(diǎn),本菜又發(fā)現(xiàn)出現(xiàn)問題的代碼里使用了spring的AOP,

于是開始懷疑是不是AOP搞鬼了,于是找了相關(guān)代碼

從這里可見這里AOP切面切點(diǎn)用在了調(diào)用controller方法前,進(jìn)而再聯(lián)想到項(xiàng)目目前的代理方式是cglib動態(tài)代理而非jdk動態(tài)代理。于是猜想是不是因?yàn)锳OP切入的時(shí)候代理未生效沒有將對應(yīng)的bean給到對應(yīng)的方法里,后面繼續(xù)深入查詢看看@Aspect使用的代理方式

鎖定這個(gè)

繼續(xù)深入,看到這里發(fā)現(xiàn)看到有ProxyCreator (代理創(chuàng)建)

判斷生成的bean是否能夠被代理

創(chuàng)建代理類bean實(shí)例

代碼較多省略了部分,這里繼續(xù)走到獲取代理

這里我們使用的是cglib動態(tài)代理

關(guān)鍵代碼判斷對應(yīng)bean是否需要被代理并返回實(shí)例

設(shè)置過濾

中間的代碼比較多,省略了部分,關(guān)鍵代碼

這里可以看到對映射的方法進(jìn)行了過濾,依次看過去發(fā)現(xiàn)這里存在疑慮

看到這里就有疑問了,因?yàn)槭褂肁OP的時(shí)候?qū)υL問修飾符是沒有啥影響的,public、private、protect都是可以的,所以最終問題應(yīng)該是這里在使用cglib的時(shí)候把私有方法過濾掉了不被代理,所以導(dǎo)致了在controller中依賴注入是成功的但調(diào)用這個(gè)接口方法時(shí)拿到的依賴為null,回看項(xiàng)目源代碼:

解決問題

把這里的private改成public就可以了…

反思

論寫代碼仔細(xì)的重要性?。?!雖然此次的事故代碼不是出自我手,但是這個(gè)小小的問題卻耗費(fèi)了我好久時(shí)間,這里讓我不得不反思下以后寫代碼要仔細(xì)仔細(xì)再仔細(xì),同時(shí)遇到bug的時(shí)候在排查問題的時(shí)候也是要仔細(xì)仔細(xì)仔細(xì)!不然很簡單的問題也是會被忽略掉。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 全面解讀Java中的枚舉類型enum的使用

    全面解讀Java中的枚舉類型enum的使用

    這篇文章主要介紹了Java中的枚舉類型enum的使用,開始之前先講解了枚舉的用處,然后還舉了枚舉在操作數(shù)據(jù)庫時(shí)的實(shí)例,需要的朋友可以參考下
    2016-04-04
  • java根據(jù)List內(nèi)對象的屬性排序方法

    java根據(jù)List內(nèi)對象的屬性排序方法

    下面小編就為大家分享一篇java根據(jù)List內(nèi)對象的屬性排序方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • Java 線程生命周期與狀態(tài)轉(zhuǎn)換的核心路徑

    Java 線程生命周期與狀態(tài)轉(zhuǎn)換的核心路徑

    本文詳細(xì)講解了Java線程的6種狀態(tài),通過4個(gè)代碼案例演示了狀態(tài)轉(zhuǎn)換的核心路徑,并介紹了使用 jstack 命令分析線程狀態(tài)的實(shí)戰(zhàn)方法,理解線程的生命周期和狀態(tài)轉(zhuǎn)換,是后續(xù)學(xué)習(xí)線程同步、線程通信的基礎(chǔ),感興趣的朋友跟隨小編一起看看吧
    2026-01-01
  • 全面詳解Spring?Bean生命周期教程示例

    全面詳解Spring?Bean生命周期教程示例

    這篇文章主要為大家介紹了Spring?Bean生命周期的全面詳解教程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 如何使用攔截器獲取請求的入?yún)⒉⑵滢D(zhuǎn)化為Java對象詳解

    如何使用攔截器獲取請求的入?yún)⒉⑵滢D(zhuǎn)化為Java對象詳解

    這篇文章主要介紹了如何使用攔截器獲取請求的入?yún)⒉⑵滢D(zhuǎn)化為Java對象的相關(guān)資料,文中介紹了兩種實(shí)現(xiàn)的方法,并給出了詳細(xì)的代碼示例,需要的朋友可以參考下
    2025-02-02
  • 一文了解MyBatis Plus批量數(shù)據(jù)插入功能

    一文了解MyBatis Plus批量數(shù)據(jù)插入功能

    mybatisPlus底層的新增方法是一條一條的新增的,下面這篇文章主要給大家介紹了MyBatis Plus批量數(shù)據(jù)插入功能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-09-09
  • SpringBoot基于docx4j實(shí)現(xiàn)DOCX轉(zhuǎn)PDF的具體方案

    SpringBoot基于docx4j實(shí)現(xiàn)DOCX轉(zhuǎn)PDF的具體方案

    在日常項(xiàng)目開發(fā)中,我們經(jīng)常遇到用戶上傳 Word( .docx)文件,希望后臺自動生成 PDF,用于下載、歸檔或在線預(yù)覽,本文將介紹一個(gè)完全開源、部署簡單、純 Java 的實(shí)現(xiàn)方案,感興趣的小伙伴可以跟著小編一起來看看
    2025-11-11
  • RabbitMQ實(shí)現(xiàn)消息可靠性傳遞過程講解

    RabbitMQ實(shí)現(xiàn)消息可靠性傳遞過程講解

    消息的可靠性傳遞是指保證消息百分百發(fā)送到消息隊(duì)列中去,這篇文章主要介紹了RabbitMQ實(shí)現(xiàn)消息可靠性傳遞過程,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05
  • SpringBoot整合HTTPS的項(xiàng)目實(shí)踐

    SpringBoot整合HTTPS的項(xiàng)目實(shí)踐

    HTTPS的主要作用是通過SSL證書保護(hù)用戶數(shù)據(jù)的安全與隱私,增加網(wǎng)站信任度,防止數(shù)據(jù)被竊取和篡改,保護(hù)網(wǎng)站免受釣魚攻擊,本文就來介紹一下,感興趣的可以了解一下
    2024-10-10
  • Servlet的線程安全問題

    Servlet的線程安全問題

    本文主要介紹了Servlet的線程安全問題,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02

最新評論

海城市| 额尔古纳市| 舒城县| 卓资县| 宿松县| 汝城县| 印江| 湘潭市| 财经| 陵水| 金平| 阿拉善左旗| 余江县| 三明市| 凤台县| 元氏县| 黄冈市| 滨州市| 颍上县| 栾城县| 西吉县| 名山县| 福鼎市| 新巴尔虎右旗| 偏关县| 合川市| 安新县| 平远县| 兴化市| 剑河县| 东山县| 龙州县| 酉阳| 遂川县| 古浪县| 内江市| 女性| 韶关市| 海晏县| 松溪县| 株洲县|