激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

香港云服务器
服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - Java 配置加載機(jī)制詳解及實(shí)例

Java 配置加載機(jī)制詳解及實(shí)例

2020-06-18 11:17lqh JAVA教程

這篇文章主要介紹了Java 配置加載機(jī)制詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下

前言

現(xiàn)如今幾乎大多數(shù)Java應(yīng)用,例如我們耳熟能詳?shù)膖omcat, struts2, netty…等等數(shù)都數(shù)不過(guò)來(lái)的軟件,要滿足通用性,都會(huì)提供配置文件供使用者定制功能。

甚至有一些例如Netty這樣的網(wǎng)絡(luò)框架,幾乎完全就是由配置驅(qū)動(dòng),這樣的軟件我們也通常稱之為”微內(nèi)核架構(gòu)”的軟件。你把它配置成什么,它就是什么。

It is what you configure it to be.

最常見(jiàn)的配置文件格式是XML, Properties等等文件。

本文探討加載配置中最通用也是最常見(jiàn)的場(chǎng)景,那就是把一個(gè)配置文件映射成Java里的POJO對(duì)象.

并探討如何實(shí)現(xiàn)不同方式的加載,例如,有一些配置是從本地XML文件里面加載的,而有一些配置需要從本地Properties文件加載,

更有甚者,有一些配置需要通過(guò)網(wǎng)絡(luò)加載配置。

如何實(shí)現(xiàn)這樣一個(gè)配置加載機(jī)制,讓我們擁有這個(gè)機(jī)制后,不會(huì)讓加載配置的代碼散布得到處都是,并且可擴(kuò)展,可管理。

 配置加載器

首先,我們需要一個(gè)配置加載器,而這個(gè)配置加載器是可以有多種不同的加載方式的,因此,我們用一個(gè)接口來(lái)描述它,如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 上午11:47:12
 * @version 1.0
 *
 */
public interface IConfigLoader<T> {
 
  /**
   * load the config typed by T
   *
   * @return
   * @throws ConfigException
   */
  public T load() throws ConfigException;
}

可是,為什么我們需要在這個(gè)接口上聲明泛型 <T> ?

很明顯,當(dāng)我們要使用一個(gè)配置加載器時(shí),你得告訴這個(gè)配置加載器你需要加載后得到什么結(jié)果。

例如,你希望加載配置后得到一個(gè) AppleConfig 對(duì)象,那么你就可以這么去使用上述定義的接口:

IConfigLoader<AppleConfig> loader = new AppleConfigLoader<AppleConfig>();
AppleConfig config = loader.load();

于是你將配置文件里的信息轉(zhuǎn)化成了一個(gè)AppleConfig對(duì)象,并且你能得到這個(gè)AppleConfig對(duì)象實(shí)例。

到目前,貌似只要我們的 AppleConfigLoader 里面實(shí)現(xiàn)了怎么加載配置文件的具體勞動(dòng),我們就可以輕易加載配置了。

可以這么說(shuō),但是不是還沒(méi)有考慮到,配置可能通過(guò)不同的方式加載呢,比如通過(guò)Properties加載,通過(guò)dom方式加載,通過(guò)sax方式加載,或者通過(guò)某些第三方的開(kāi)源庫(kù)來(lái)加載。

因此,除了 配置加載器 ,我們還需要另外一種角色,配置加載方式的提供者。暫且,我們就叫它IConfigProvider。

配置加載方式的提供者

配置加載方式的提供者可以提供一種加載方式給配置加載器,換言之,提供一個(gè) 對(duì)象 給配置加載器。

  1. 如果通過(guò)dom方式加載,那么 提供者 提供一個(gè) Document 對(duì)象給 加載器 。
  2. 如果通過(guò)Properties方式加載,那么 提供者 提供一個(gè) Properties 對(duì)象給 加載器
  3. 如果通過(guò)第三方類庫(kù)提供的方式加載,比如apache-commons-digester3(tomcat的配置加載),那么 提供者 提供一個(gè) Digester 對(duì)象給 加載器

提供者的職責(zé)就是 提供 ,僅此而已,只提供配置加載器所需要的對(duì)象,但它本身并不參與配置加載的勞動(dòng)。

我們用一個(gè)接口 IConfigProvider 來(lái)定義這個(gè) 提供者

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 上午11:54:28
 * @version 1.0
 *
 */
public interface IConfigProvider<T> {
 
  /**
   * provide a config source used for loading config
   *
   * @return
   * @throws ConfigException
   */
  public T provide() throws ConfigException;
}

這里為什么又會(huì)有 <T> 來(lái)聲明泛型呢?

如果需要一個(gè)提供者,那么至少得告訴這個(gè)提供者它該提供什么吧。

因此,一個(gè)提供者會(huì)提供什么,由這個(gè)來(lái)決定。

同時(shí),到這里,我們可以先建造一個(gè)工廠,讓它來(lái)生產(chǎn)特定的提供者:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 上午11:56:28
 * @version 1.0
 *
 */
public class ConfigProviderFactory {
 
  private ConfigProviderFactory() {
    throw new UnsupportedOperationException("Unable to initialize a factory class : "
        + getClass().getSimpleName());
  }
 
  public static IConfigProvider<Document> createDocumentProvider(String filePath) {
    return new DocumentProvider(filePath);
  }
 
  public static IConfigProvider<Properties> createPropertiesProvider(String filePath) {
    return new PropertiesProvider(filePath);
  }
 
  public static IConfigProvider<Digester> createDigesterProvider(String filePath) {
      return new DigesterProvider(filePath);
  }
}

可以開(kāi)始實(shí)現(xiàn)具體配置加載器了?

還不行!

到這里,假設(shè)我們有一個(gè)配置文件,叫apple.xml。而且我們要通過(guò)DOM方式把這一份apple.xml加載后變成AppleConfig對(duì)象。

那么,首先我要通過(guò)提供者工廠給我制造一個(gè)能提供Document的提供者。然后拿到這個(gè)提供者,我就可以調(diào)用它的provide方法來(lái)獲得Document對(duì)象,有了document對(duì)象,那么我就可以開(kāi)始來(lái)加載配置了。

可是,如果要加載BananaConfig、PearConfig…….呢,其步驟都是一樣的。因此我們還要有一個(gè)抽象類,來(lái)實(shí)現(xiàn)一些默認(rèn)的共同行為。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 上午11:59:19
 * @version 1.0
 *
 */
public abstract class AbstractConfigLoader <T, U> implements IConfigLoader<T>{
 
  protected IConfigProvider<U> provider;
 
  protected AbstractConfigLoader(IConfigProvider<U> provider) {
    this.provider = provider;
  }
 
  /*
   * @see IConfigLoader#load()
   */
  @Override
  public T load() throws ConfigException {
    return load(getProvider().provide());
  }
 
  public abstract T load(U loaderSource) throws ConfigException;
 
  protected IConfigProvider<U> getProvider() {
    return this.provider;
  }
}

每個(gè)配置加載器都有一個(gè)帶參數(shù)構(gòu)造器,接收一個(gè)Provider。

泛型指明了我要加載的是AppleConfig還是BananConfig,泛型 <U> 指明了要用什么加載方式加載,是Document呢,還是Properties,或者其他。

實(shí)戰(zhàn)運(yùn)用實(shí)例

有一份菜市場(chǎng)配置文件market.xml,配置了菜市場(chǎng)的商品,里面有兩種商品,分別是蘋果和雞蛋。

?
1
2
3
4
5
6
7
8
9
<market>
  <apple>
    <color>red</color>
    <price>100</price>
  </apple>
  <egg>
    <weight>200</weight>
  </egg>
</market>

另外還有一份關(guān)于各個(gè)檔口老板名字的配置文件,owner.properties

port1=Steve Jobs
port2=Bill Gates
port3=Kobe Bryant

我們先定義好如下類:MarketConfig.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 下午11:03:37
 * @version 1.0
 *
 */
public class MarketConfig {
 
  private AppleConfig appleConfig;
  private EggConfig eggConfig;
  private OwnerConfig ownerConfig;
 
  public AppleConfig getAppleConfig() {
    return appleConfig;
  }
  public void setAppleConfig(AppleConfig appleConfig) {
    this.appleConfig = appleConfig;
  }
  public EggConfig getEggConfig() {
    return eggConfig;
  }
  public void setEggConfig(EggConfig eggConfig) {
    this.eggConfig = eggConfig;
  }
  public OwnerConfig getOwnerConfig() {
    return ownerConfig;
  }
  public void setOwnerConfig(OwnerConfig ownerConfig) {
    this.ownerConfig = ownerConfig;
  }
}

AppleConfig.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 下午11:03:45
 * @version 1.0
 *
 */
public class AppleConfig {
 
  private int price;
  private String color;
 
  public void setPrice(int price) {
    this.price = price;
  }
 
  public int getPrice() {
    return this.price;
  }
 
  public void setColor(String color) {
    this.color = color;
  }
 
  public String getColor() {
    return this.color;
  }
}

EggConfig.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 下午11:03:58
 * @version 1.0
 *
 */
public class EggConfig {
 
  private int weight;
 
  public void setWeight(int weight) {
    this.weight = weight;
  }
 
  public int getWeight() {
    return this.weight;
  }
}

OwnerConfig.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 下午11:04:06
 * @version 1.0
 *
 */
public class OwnerConfig {
 
  private Map<String, String> owner = new HashMap<String, String>();
 
  public void addOwner(String portName, String owner) {
    this.owner.put(portName, owner);
  }
 
  public String getOwnerByPortName(String portName) {
    return this.owner.get(portName);
  }
 
  public Map<String, String> getOwners() {
    return Collections.unmodifiableMap(this.owner);
  }
}

這個(gè)例子有兩種配置加載方式,分別是Dom和Properties加載方式。

所以我們的提供者建造工廠需要制造兩種提供者provider.

而且需要定義2個(gè)配置加載器,分別是:

OwnerConfigLoader

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 下午11:24:50
 * @version 1.0
 *
 */
public class OwnerConfigLoader extends AbstractConfigLoader<OwnerConfig, Properties>{
 
  /**
   * @param provider
   */
  protected OwnerConfigLoader(IConfigProvider<Properties> provider) {
    super(provider);
  }
 
  /*
   * @see AbstractConfigLoader#load(java.lang.Object)
   */
  @Override
  public OwnerConfig load(Properties props) throws ConfigException {
    OwnerConfig ownerConfig = new OwnerConfig();
 
    /**
     * 利用props,設(shè)置ownerConfig的屬性值
     *
     * 此處代碼省略
     */
    return ownerConfig;
  }
}

然后是MarketConfigLoader

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import org.w3c.dom.Document;
 
/**
 *
 *
 * @author Bean
 * @date 2016年1月21日 下午11:18:56
 * @version 1.0
 *
 */
public class MarketConfigLoader extends AbstractConfigLoader<MarketConfig, Document> {
 
  /**
   * @param provider
   */
  protected MarketConfigLoader(IConfigProvider<Document> provider) {
    super(provider);
  }
 
  /*
   * AbstractConfigLoader#load(java.lang.Object)
   */
  @Override
  public MarketConfig load(Document document) throws ConfigException {
 
    MarketConfig marketConfig = new MarketConfig();
    AppleConfig appleConfig = new AppleConfig();
    EggConfig eggConfig = new EggConfig();
    /**
     * 在這里處理document,然后就能得到
     * AppleConfig和EggConfg
     *
     * 此處代碼省略
     */
    marketConfig.setAppleConfig(appleConfig);
    marketConfig.setEggConfig(eggConfig);
 
    /**
     * 由于OwnerConfig是需要properties方式來(lái)加載,不是xml
     * 所以這里要新建一個(gè)OwnerConfigLoader,委托它來(lái)加載OwnerConfig
     */
 
    OwnerConfigLoader ownerConfigLoader = new OwnerConfigLoader(ConfigProviderFactory.createPropertiesProvider(YOUR_FILE_PATH));
    OwnerConfig ownerConfig = ownerConfigLoader.load();
 
    marketConfig.setOwnerConfig(ownerConfig);
 
    return marketConfig;
  }
}

然后,我們?cè)趹?yīng)用層面如何獲取到MarketConfig呢

?
1
2
MarketConfigLoader marketConfigLoader = new MarketConfigLoader(ConfigProviderFactory.createDocumentProvider(YOUR_FILE_PATH));
MarketConfig marketConfig = marketConfigLoader.load();

也許有個(gè)地方會(huì)人奇怪,明明有四個(gè)配置類,為什么只有2個(gè)配置加載器呢。因?yàn)镸arketConfig、EggConfig和AppleConfig,都是從同一個(gè)xml配置文件里面加載,所以只要一個(gè)Document對(duì)象,通過(guò)MarketConfigLoader就可以全部加載。

而OwnerConfig是不同的加載方式,所以需要另外一個(gè)加載器。

總結(jié)

本文提出的配置加載機(jī)制,并不能夠?qū)嶋H幫忙加載配置,這事應(yīng)該留給DOM,SAX,以及其他一些開(kāi)源庫(kù)如dom4j,Digester去做。但本文提出的配置加載機(jī)制能夠讓配置加載機(jī)制更靈活,容易擴(kuò)展,并且能夠集成多種配置加載方式,融合到一個(gè)機(jī)制進(jìn)來(lái),發(fā)揮各自有點(diǎn)。

實(shí)際上,有些軟件經(jīng)常需要同時(shí)從多種不同格式的配置文件里面加載配置,例如struts2,以及我最近在研究并被氣到吐血的某國(guó)產(chǎn)開(kāi)源數(shù)據(jù)庫(kù)中間件軟件,如果沒(méi)有一套完整的配置加載機(jī)制,那么代碼會(huì)比較散亂,可維護(hù)性不高。容易使人吐血。

通過(guò)此文希望大家理解并掌握 Java 配置加載機(jī)制的知識(shí),謝謝大家對(duì)本站的支持!

延伸 · 閱讀

精彩推薦
336
主站蜘蛛池模板: 久久99国产精品免费网站 | 91性高湖久久久久久久久网站 | 中文日产幕无线码6区免费版 | 毛片视频网站在线观看 | 亚州综合图片 | 国产九色视频在线观看 | 久久福利电影网 | 美女久久久久 | 国产一级二级在线播放 | 久久久精品精品 | 国产宾馆3p国语对白 | 亚洲精品无码不卡在线播放he | 国产精品99久久久久久大便 | 精品国产91久久久久久浪潮蜜月 | 国产成人强伦免费视频网站 | 欧美18一12sex性处hd | 国产在线精品一区二区夜色 | 一级电影中文字幕 | 鲁丝一区二区二区四区 | av在线等| 少妇一级淫片免费放正片 | 欧美激情精品久久久久 | 久久性生活免费视频 | 久久久久se| 青青操精品 | 日本成人高清视频 | 91短视频在线视频 | 日本成年免费网站 | 亚洲av毛片成人精品 | 精品二区在线观看 | 538任你躁在线精品视频网站 | 草b视频在线观看 | 亚洲xxx视频 | 精国产品一区二区三区 | 亚州综合 | 久久网国产精品 | 黄色网电影 | 性少妇videosexfreexx | 黄色片免费在线 | 国产精品久久久久久久久久10秀 | 欧美亚洲国产一区二区三区 |