天天看點

踩坑:Spring靜态變量/構造函數注入失敗(注入為null)問題的解決方案

案例代碼如下:

@Component
public class HelloWorld {
   /**
    * 錯誤案例:這種方式是不能給靜态變量注入屬性值的
    */
    @Value("${hello.world}")
    public static String HELLO_WORLD;
}      

解決方案一:

@Value

注解加在setter方法上面

@Component
public class HelloWorld {
    public static String HELLO_WORLD;
    
    @Value("${hello.world}")
    public void setHELLO_WORLD(String HELLO_WORLD) {
        this.HELLO_WORLD = HELLO_WORLD;
    } 
}
      

解決方案二:

@PostConstruct

注解

因為

@PostConstruct

注解修飾的方法加在順序在構造方法之後靜态變量指派之前,是以可以通過該注解解決靜态變量屬性值注入失敗問題:

@Component
public class HelloWorld {
    public static String HELLO_WORLD;
  
    @Value("${hello.world}")
    public static String helloWorld;
    
    @PostConstruct
    public void init(){
        // 為靜态變量指派(值為從Spring IOC容器中擷取的hello.world字段值)
        HELLO_WORLD = this.helloWorld;
    } 
}
      

2、案例2:在構造函數中使用Spring容器中的Bean對象,得到的結果為空

業務場景假設:

eg:我需要在一個類(HelloWorld)被加載的時候,調用service層的接口(UserService)去執行一個方法(sayHello),有些同學可能會在構造函數中通過調用UserService的sayHello()去實作這個需求,但是這會導緻一些錯誤異常,請看下面的示例。

錯誤示範代碼如下:

@Component
public class HelloWorld {
     
   /**
    * UserService注入
    */
    @Autowired
    private UserService userService;

    public HelloWorld(){
       // 這裡會報空指針異常:因為 userService 的屬性注入是在無參數構造函數之後,如果這裡直接使用 userService ,此時該屬性值為null,一個為null的成員變量調用sayHello()方法,NullPointException 異常是情理之中呀!
       userService.sayHello("hello tiandai!");
    }
}
      

解決方案:

@PostConstruct

由于

@PostConstruct

注解修飾的方法其生命周期位于構造方法調用之後,在Spring屬性值注入之前,是以,該注解可以很好的解決這個業務需求,代碼如下:

@Component
public class HelloWorld {
     
   /**
    * UserService注入
    */
    @Autowired
    private UserService userService;

    public HelloWorld(){
    }
  
    @PostConstruct
    public void init(){
       userService.sayHello("hello tiandai!");
    } 
}
      

關于這一部分問題,還有一些奇奇怪怪的用法,參考文章:

https://blog.csdn.net/dream19990329/article/details/106274283