從static變量初始化到Spring/Spring boot的工具類靜態(tài)變量注入

引入

寫這篇博文,要從java.lang.ExceptionInInitializerError這個(gè)報(bào)錯(cuò)開始。簡(jiǎn)單的看上去,這是一個(gè)類初始化異常報(bào)錯(cuò)撤蟆。但事實(shí)上并不是這樣,這是由于調(diào)用某個(gè)static變量屬性時(shí)而該屬性沒有初始化而導(dǎo)致的錯(cuò)誤堂污,所以家肯,在debug模式下,你第二次再嘗試調(diào)用操作static屬性的方法時(shí)盟猖,可能就會(huì)拋出一個(gè)空指針異常了讨衣。據(jù)聽請(qǐng)看這段代碼。

Domain.java

public class Domain {

    private static Domain domain = new Domain();

    private static Map<String,String> domainMap = new HashMap<String
            ,String>();

    private Domain() {
        domainMap.put("isTrue","true");
    }

    public static Domain getInstance() {
        return domain;
    }
}


TestDomain.java

public class TestDomain {
    public static void main(String[] args) {
        String domainString = Domain.getInstance().toString();
        System.out.println(domainString);
    }
}

在執(zhí)行調(diào)用的時(shí)候就會(huì)報(bào)錯(cuò)了式镐!那原因是什么呢反镇?
原因還是很簡(jiǎn)單的,在調(diào)用Domain靜態(tài)方法時(shí)娘汞,由于兩個(gè)變量都是靜態(tài)變量歹茶,不會(huì)對(duì)它進(jìn)行賦值,但會(huì)對(duì)變量按順序進(jìn)行初始化你弦。所以先給domain初始化辆亏,這個(gè)時(shí)候調(diào)用私有構(gòu)造函數(shù),函數(shù)內(nèi)已經(jīng)用到了domainMap,而這個(gè)變量還沒有初始化鳖目,進(jìn)而拋出了沒有初始化類的異常扮叨。
想要解決這個(gè)異常,兩種方案领迈。

  • 把domain和domainMap的變量聲明位置調(diào)換彻磁,這樣在調(diào)用私有構(gòu)造函數(shù)時(shí)domainMap已經(jīng)初始化了。
  • 將domain的構(gòu)造函數(shù)公有化狸捅,并使外部調(diào)用來初始化衷蜓,而不是聲明時(shí)即初始化。當(dāng)然這樣并不符合工具類的使用方便尘喝,會(huì)造成浪費(fèi)內(nèi)存等后果磁浇。

漸進(jìn)

之所以舉上面這個(gè)例子,是因?yàn)樗臉?gòu)造很像工具類朽褪。
首先你得明白什么是工具類置吓,簡(jiǎn)單來說它是一種可以不用初始化對(duì)象而直接調(diào)用其靜態(tài)方法而達(dá)到某一些功能的以Utils或Helper結(jié)尾的類。說到這里缔赠,要聲明一下衍锚,并不是所有的靜態(tài)類都是推薦使用的,使用靜態(tài)類的過程往往只是為了閱讀方便和調(diào)用簡(jiǎn)單嗤堰,但卻不知會(huì)增加程序的耦合度戴质,破壞設(shè)計(jì)模式等缺點(diǎn)。這里貼一篇文章寫的很不錯(cuò):如何擺脫工具類
而我們最終的問題是告匠,如何在工具類中初始化賦值靜態(tài)屬性呢戈抄。項(xiàng)目環(huán)境是在spring框架下,舉個(gè)例子:

XXXProperties.java

public class XXXProperties {

    private String staticParam1;

    private String staticParam2;

    public String getStaticParam1() {
        return staticParam1;
    }

    public void setStaticParam1(String staticParam1) {
        this.staticParam1 = staticParam1;
    }

    public String getStaticParam2() {
        return staticParam2;
    }

    public void setStaticParam2(String staticParam2) {
        this.staticParam2 = staticParam2;
    }

}

XXUtils.java

public class XXUtils {

    @Autowired //靜態(tài)變量通過spring并不能直接注入后专,所以這樣是會(huì)報(bào)錯(cuò)的
    private static XXXProperties xxxProperties;

    private static String do() {
        String xxxPropertiesSize = xxxProperties.getSize();
        return xxxPropertiesSize;
    }
}

當(dāng)外部想要調(diào)用XXUtilsdo()時(shí)划鸽,發(fā)現(xiàn)xxxProperties并沒有注入值,而我們?nèi)フ{(diào)用時(shí)行贪,程序也自然會(huì)拋出文章開始說的異常漾稀。

怎么去注入呢?

方案

  1. 采用間接注入方式
//可以換成@Configuration,與@Inject配合使用
@Component
public class XXUtils {

    //可以換成@Inject
    @Resource
    private XXXProperties xxxPropertiesAutowired;

    private static XXXProperties xxxProperties;

    @PostConstruct
    public void init() {
       this.xxxProperties = xxxPropertiesAutowired;
    }
}

也可以使用在Spring Boot中使用 @ConfigurationProperties 注解 給出的注解方式建瘫,是針對(duì)spring-boot的崭捍。

  1. 將靜態(tài)參數(shù)用beans提取,以鍵值對(duì)形式存儲(chǔ)啰脚,在工具類中直接調(diào)用
配置

應(yīng)用

其中

public class org.springframework.beans.factory.config.PropertyPlaceholderConfigurer extends org.springframework.beans.factory.config.PlaceholderConfigurerSupport
  1. 如果你不想提取bean,也可以直接讀取file.
public class XMLConfig {
      private static final Logger logger = Logger.getLogger(XMLConfig.class);
      public static final String            FILEPATH         = "xmlconf.properties";
      public static long                    fileLastModified = 0;

      //屬性文件xmlconf.properties中對(duì)應(yīng)的各個(gè)鍵值對(duì)
      public static HashMap<String, String> paramsMap    = new HashMap<String, String>();

      public static HashMap<String, String> loadProperties(String file)
      {
          HashMap<String, String> map = new HashMap<String, String>();
          InputStream in = null;
          Properties p = new Properties();
          try
          {
              in = new BufferedInputStream(new FileInputStream(file));

              p.load(in);
          }
          catch (FileNotFoundException e)
          {
              logger.error(file + " is not exists!");
          }
          catch (IOException e)
          {
              logger.error("IOException when load " + file);
          }
          finally
          {
              if (in != null)
              {
                  try
                  {
                      in.close();
                  }
                  catch (IOException e)
                  {
                      logger.error("Close IO error!");
                  }
              }
          }

          Set<Entry<Object, Object>> set = p.entrySet();
          Iterator<Entry<Object, Object>> it = set.iterator();
          while (it.hasNext())
          {
              Entry<Object, Object> entry = it.next();
              String key = (String) entry.getKey();
              String value = (String) entry.getValue();
              logger.debug(key + "=" + value);
              // System.out.println(key + "=" + value);
              if (key != null && value != null)
              {
                  map.put(key.trim(), value.trim());
              }
          }

          return map;
      }

}
  1. 待你完善
    期待有更好的方法一起交流討論殷蛇。

參考

java.lang.ExceptionInInitializerError的原因

java.lang.ExceptionInInitializerError in Connection Factory

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市橄浓,隨后出現(xiàn)的幾起案子粒梦,更是在濱河造成了極大的恐慌,老刑警劉巖荸实,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匀们,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡准给,警方通過查閱死者的電腦和手機(jī)泄朴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來露氮,“玉大人祖灰,你說我怎么就攤上這事∨瞎妫” “怎么了局扶?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)叁扫。 經(jīng)常有香客問我三妈,道長(zhǎng),這世上最難降的妖魔是什么陌兑? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任沈跨,我火速辦了婚禮,結(jié)果婚禮上兔综,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好软驰,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布涧窒。 她就那樣靜靜地躺著,像睡著了一般锭亏。 火紅的嫁衣襯著肌膚如雪纠吴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天慧瘤,我揣著相機(jī)與錄音戴已,去河邊找鬼。 笑死锅减,一個(gè)胖子當(dāng)著我的面吹牛糖儡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播怔匣,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼握联,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了每瞒?” 一聲冷哼從身側(cè)響起金闽,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎剿骨,沒想到半個(gè)月后代芜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浓利,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年挤庇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荞膘。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡罚随,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出羽资,到底是詐尸還是另有隱情淘菩,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布屠升,位于F島的核電站潮改,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏腹暖。R本人自食惡果不足惜汇在,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望脏答。 院中可真熱鬧糕殉,春花似錦亩鬼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至羡洁,卻和暖如春玷过,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筑煮。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國(guó)打工辛蚊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人真仲。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓袋马,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親袒餐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子飞蛹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法灸眼,內(nèi)部類的語(yǔ)法卧檐,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法焰宣,線程的語(yǔ)...
    子非魚_t_閱讀 31,587評(píng)論 18 399
  • 從三月份找實(shí)習(xí)到現(xiàn)在霉囚,面了一些公司,掛了不少匕积,但最終還是拿到小米盈罐、百度、阿里闪唆、京東盅粪、新浪、CVTE悄蕾、樂視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,194評(píng)論 11 349
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理票顾,服務(wù)發(fā)現(xiàn),斷路器帆调,智...
    卡卡羅2017閱讀 134,601評(píng)論 18 139
  • (一)Java部分 1奠骄、列舉出JAVA中6個(gè)比較常用的包【天威誠(chéng)信面試題】 【參考答案】 java.lang;ja...
    獨(dú)云閱讀 7,071評(píng)論 0 62
  • 雖然當(dāng)時(shí)他還不知道書法以后有什么作用,但事實(shí)證明番刊,叫不死的藝術(shù)修養(yǎng)是的蘋果公司所有的產(chǎn)品都設(shè)計(jì)的非常漂亮含鳞。 在美國(guó)...
    王老劉閱讀 197評(píng)論 0 0