問題描述:
DatabaseConfig:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "database")
public class DatabaseConfig {
private static String url;
private static String user;
private static String password;
private static String driver;
//getter
//setter
}
DatabaseConfig是為了讀入配置信息的一個基礎類,目的是在DB類在初始化時,能夠獲取配置信息。
正確的DB類初始化方法,是將初始化代碼放在一個函數里,并用注解@PostConstruct標記,PostConstruct是指在類型創建之后,才會執行,這樣能夠保證所有的依賴均已添加。
@Configuration
@ConfigurationProperties(prefix = "database")
public class DB {
private static String url ;
private static String user ;
private static String password ;
private static String driver ;
protected static SqlConnector conn;
@PostConstruct
private static void initialize(){
System.out.println("db");
ApplicationContext context = new AnnotationConfigApplicationContext(DatabaseConfig.class);
DatabaseConfig config = context.getBean(DatabaseConfig.class);
conn = new SqlConnector(config.getUrl(), config.getUser(), config.getPassword(), config.getDriver());
}
}
錯誤的初始化方式。如代碼所示,DB類中的變量均為靜態變量,之前代碼將這些靜態變量的初始化放在一個static block中,但會發現,靜態變量的初始化,將先于spring注冊bean。也就是說,當靜態塊執行時,spring尚未注入已生命的bean,即DatabaseConfig,這樣就使得Database中的變量還尚未被初始化,所以獲取的是null。
@Configuration
@ConfigurationProperties(prefix = "database")
public class DB {
private static String url ;
private static String user ;
private static String password ;
private static String driver ;
protected static SqlConnector conn;
static{
ApplicationContext context = new AnnotationConfigApplicationContext(DatabaseConfig.class);
DatabaseConfig config = context.getBean(DatabaseConfig.class);
//這種方式獲取的url等均為null
conn = new SqlConnector(config.getUrl(), config.getUser(), config.getPassword(), config.getDriver());
}
}
還有一點需要注意的是,配置信息變量需要聲明為靜態變量。我推敲的結果,認為用@Configuraiton注解后的類,是會被spring當做一個bean添加到容器中,因為是Configuration,會出發自動執行類的域的setter方法,這樣使得static的配置信息能夠得到初始化。