spingboot使用@Resource注入靜態變量報空指針的問題解決


一、業務場景

在實現doorls7動態調用java靜態方法的過程中,java靜態方法需要依賴被容器管理的類,就像這樣:

@Component
public class RuleFunctions {
  @Resource
  private static RuleEntityItemInfoBiz ruleEntityItemInfoBiz;

  public static double calculateCurrentMonthIncomeTax(String fileId, String salaryMonth, String taxPlanId){
    //此處省略方法實現邏輯
  }

}
如果直接這樣去調用calculateCurrentMonthIncomeTax方法,那么控制台一定會報java.lang.IllegalStateException: @Resource annotation is not supported on static fields異常。

注意:這里並不是spring未注入依賴,而是被static方法初始化時給清空了。

二、原理剖析

靜態變量、類變量,並不是對象的屬性,而是一個類的屬性;所以靜態方法是屬於整個類(class)的,普通方法才是屬於實體對象(也就是New出來的對象)的,spring注入是在容器中實例化對象,所以不能使用靜態方法。

而使用靜態變量、類變量擴大了靜態方法的使用范圍。在靜態方法中注入依賴在spring框架中是不推薦使用的,依賴注入的主要目的,是讓容器去產生一個對象的實例,然后在整個生命周期中使用他們,同時也讓測試工作更加容易。

一旦你使用靜態方法,就不再需要去產生這個類的實例,這會讓測試變得更加困難,同時你也不能為一個給定的類,依靠注入方式去產生多個具有不同的依賴環境的實例,這種static field是隱含共享的,並且是一種global全局狀態,spring同樣不推薦這樣去做。

三、解決方法

1、將@Autowire加到構造方法上

@Component
public class RuleFunctions {
  @Resource
  private static RuleEntityItemInfoBiz ruleEntityItemInfoBiz;
  
  @Autowired
  public RuleFunctions(RuleEntityItemInfoBiz ruleEntityItemInfoBiz) {
    RuleFunctions.ruleEntityItemInfoBiz = ruleEntityItemInfoBiz;
  }
  public static double calculateCurrentMonthIncomeTax(String fileId, String salaryMonth, String taxPlanId){
    //此處省略方法實現邏輯
  }
}


2.使用set注入的方式

@Component
public class RuleFunctions {
  @Resource
  private static RuleEntityItemInfoBiz ruleEntityItemInfoBiz;
  
  @Autowired
  public void setRuleEntityItemInfoBiz(RuleEntityItemInfoBiz ruleEntityItemInfoBiz) {
    RuleFunctions.ruleEntityItemInfoBiz = ruleEntityItemInfoBiz;
  }
  public static double calculateCurrentMonthIncomeTax(String fileId, String salaryMonth, String taxPlanId){
    //此處省略方法實現邏輯
  }
}

3.用@PostConstruct注解

@Component
public class RuleFunctions {
  @Resource
  private RuleEntityItemInfoBiz ruleEntityItemInfoBiz;

  private static RuleEntityItemInfoBiz staticRuleEntityItemInfoBiz;  

  /**
  *注釋用於在完成依賴注入以后執行任何初始化之后需要執行的方法。必須在類投入使用之前調用此方法。
  */
  @PostConstruct
  public void beforeInit() {
    staticRuleEntityItemInfoBiz = ruleEntityItemInfoBiz;
  }
  public static double calculateCurrentMonthIncomeTax(String fileId, String salaryMonth, String taxPlanId){
    //此處省略方法實現邏輯
  }
}

四:@PostConstruct注解的說明

@PostConstruct該注解是javax.annotation包下的,被用來修飾一個非靜態的void()方法。被@PostConstruct修飾的方法會在服務器加載Servlet的時候運行,並且只會被服務器執行一次。PostConstruct在構造函數之后執行,init()方法之前執行。

@PostConstruct注釋規則:除了攔截器這個特殊情況以外,其他情況都不允許有參數,否則spring框架會報IllegalStateException;而且返回值要是void,但實際也可以有返回值,至少不會報錯,只會忽略
通常我們會是在Spring框架中使用到@PostConstruct注解 該注解的方法在整個Bean初始化中的執行順序:

Constructor(構造方法) -> @Autowired(依賴注入) -> @PostConstruct(注釋的方法)

轉載於:https://www.cnblogs.com/chenfeng1122/p/6270217.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM