1. 程式人生 > >Spring的注入方式--構造方法--解決需要在構造方法裡面去初始化全域性變數

Spring的注入方式--構造方法--解決需要在構造方法裡面去初始化全域性變數

構造方法注入

public class UserService implements IUserService {

    private IUserDao userDao;

    public UserService(IUserDao userDao) {
        this.userDao = userDao;
    }

}

先看一段程式碼,下面的程式碼能執行成功嗎?

@Autowired
 private User user;
 private String school;
 
 public UserAccountServiceImpl(){
     this.school = user.getSchool();
 }

答案是不能。

  因為Java類會先執行構造方法,然後再給註解了@Autowired 的user注入值,所以在執行構造方法的時候,就會報錯。

  報錯資訊可能會像下面:
  Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name '...' defined in file [....class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [...]: Constructor threw exception; nested exception is java.lang.NullPointerException
  報錯資訊說:建立Bean時出錯,出錯原因是例項化bean失敗,因為bean時構造方法出錯,在構造方法裡丟擲了空指標異常。

  解決辦法是,使用構造器注入,如下:

private User user;
 private String school;
 
 @Autowired
 public UserAccountServiceImpl(User user){
     this.user = user;
     this.school = user.getSchool();
 }

可以看出,使用構造器注入的方法,可以明確成員變數的載入順序

PS:Java變數的初始化順序為:靜態變數或靜態語句塊–>例項變數或初始化語句塊–>構造方法–>@Autowired

通過這種方法你可以實現呼叫某個Service的方法來初始化一些全域性引數,或者做快取預載入等。

還有另外一種方法也可以實現,那就是

@Component
@Order(10)
public class Init implements ApplicationRunner {
    public void init() {
        // do something
    }
}

這種方式是在APP啟動之後去初始化,也可以實現初始化全域性引數