目錄
- 前言
- 1. 問題所示
- 2. 原理分析
- 3. 解決方法
前言
試錯了一小時,發現接口返回null!!
最后梳理其知識點并總結其原理
1. 問題所示
接口類如下:
public interface IInfoService extends BaseService<Info> {
錯誤方式一:(此處infoservice返回null值)
錯誤方式二:(不使用注解,通過new實例化 也返回null值)
2. 原理分析
在Spring MVC中,
@Autowired
和@Resource
等注解通常用于在Controller中注入Service,這是因為在Spring MVC中,Controller屬于Spring容器的一部分,因此可以自動注入其他由Spring管理的Bean,如Service然而,在一般的類中,如果想要使用Service,直接使用new關鍵字實例化一個Service對象是不可取的
這是因為通過new實例化的對象是脫離了Spring容器的管理的,因此無法獲取到Spring容器中的注解屬性值,這樣可能會導致注入的Service為null。
即使該類被標記為@Component
并且被Spring管理,直接通過new實例化Service的方式也無法注入依賴,因為這個實例不受Spring容器的管控。為了解決這個問題,應該讓這個一般類也成為Spring容器的一個Bean,方法是使用
@Component
或者相關的注解,如@Service
、@Repository
等。然后,在需要使用Service的地方,通過注入的方式將Service注入到這個一般類中,而不是通過new關鍵字實例化。這樣就能保證依賴注入成功,避免出現null的情況。
在實踐中,確保了類成為了Spring容器的一個Bean,并使用了適當的注解來進行依賴注入,可以有效避免由于依賴注入失敗而導致的空指針異常等問題
springboot不支持注入靜態屬性,使用`@Autowired等注解注入會失敗
3. 解決方法
使用如下方式:
@Component
public class CommonUtil {@Autowiredprivate IInfoService infoService;public static CommonUtil commonUtil;@PostConstructpublic void init() {commonUtil = this;}
最終在調用inforservice方法時,通過使用commonUtil.infoService.list
主要的步驟邏輯如下:
@Component
注解標記了CommonUtil類,使其成為了Spring容器的一個Bean,因此Spring會對其進行管理@Autowired
注解標記了infoService字段,告訴Spring在初始化CommonUtil的時候,自動注入一個IInfoService類型的實例@PostConstruct
注解標記了init()方法,這意味著在CommonUtil實例創建完成并且所有的依賴注入完成后,Spring會調用init()方法。在init()方法中,將當前實例賦值給了靜態的commonUtil對象- 通過將commonUtil對象設置為靜態的,使得其他類可以通過CommonUtil.commonUtil來訪問CommonUtil類的實例,從而間接獲取到了IInfoService的實例
這種方法雖然能夠解決在普通類中使用Service的問題,但要注意以下幾點:
- 靜態變量commonUtil可能存在線程安全問題,如果多個線程同時訪問該變量,可能會出現競態條件。
- 靜態變量的使用會增加類的耦合度,降低代碼的可維護性和可測試性。