1. Bean依賴關系
一個配置類的Bean,一個實例Bean;
實例Bean初始化時需要依賴配置類的Bean;
1.1 配置類Bean
@ConfigurationProperties(prefix = "system") public class SystemConfig { private Integer type; private String rootPath; }
1.2 實例Bean
@Component public class HDFSFileHandler implements FileHandler { @Autowired private SystemConfig config; private FileSystem fileSystem; public HDFSFileHandler(){ start(); } /** * 初始化 fileSystem */ private void start() { try { // 此處 config 空指針異常 if (SystemConstant.FILE_SYSTEM_HDFS.equals(config.getType())){ String uri = "hdfs://" + config.getHdfsIp() + ":" + config.getHdfsPort(); fileSystem = FileSystem.get(new URI(uri), new Configuration(), "hadoop"); log.debug("uri:" + uri); log.debug("fileSystem:" + fileSystem); } } catch (Exception e) { log.error("init fileSystem occur a exception",e); } } }
2. 問題現象
實例Bean初始化時配置類Bean空指針異常;

3. 原因分析
spring在實例化Bean時,先通過反射調用構造方法生成一個基本對象,然后再填充屬性(參考:spring bean 的生命周期);
填充屬性之前屬性值都為默認值,引用類為null,構造方法中使用屬性對象時屬性對象還未被設置,所以為null;
4. 解決方案
4.1 方案一
構造器中將Bean作為參數顯式的傳入;
@Component public class HDFSFileHandler implements FileHandler { private SystemConfig config; private FileSystem fileSystem; // 構造器顯式傳入參數 public HDFSFileHandler(SystemConfig config) { this.config = config; start(); } /** * 初始化 fileSystem */ private void start() { try { if (SystemConstant.FILE_SYSTEM_HDFS.equals(config.getType())){ String uri = "hdfs://" + config.getHdfsIp() + ":" + config.getHdfsPort(); fileSystem = FileSystem.get(new URI(uri), new Configuration(), "hadoop"); log.debug("uri:" + uri); log.debug("fileSystem:" + fileSystem); } } catch (Exception e) { log.error("init fileSystem occur a exception",e); } } }
4.2 @Autowired + @PostConstruct
@Component public class HDFSFileHandler implements FileHandler { @Autowired private SystemConfig config; private FileSystem fileSystem; public HDFSFileHandler() { start(); } /** * 初始化 fileSystem */ @PostConstruct private void start() { try { if (SystemConstant.FILE_SYSTEM_HDFS.equals(config.getType())){ String uri = "hdfs://" + config.getHdfsIp() + ":" + config.getHdfsPort(); fileSystem = FileSystem.get(new URI(uri), new Configuration(), "hadoop"); log.debug("uri:" + uri); log.debug("fileSystem:" + fileSystem); } } catch (Exception e) { log.error("init fileSystem occur a exception",e); } } }
