google guice 綁定常量的另類用法----讀取并注入配置信息
初學(xué)guice,每每看到guice 綁定常量的用法介紹,總是在想這個(gè)功能有什么用處?實(shí)在想不出來(lái)用它的場(chǎng)合和優(yōu)點(diǎn),感覺(jué)頗為雞肋。今天閑坐家中,又無(wú)聊翻書打發(fā)時(shí)間,再次看到這個(gè)東東,作者和我似乎有相同的想法,不過(guò)他的一句“既然我們可以使用自定義注解,那么這里也可以替換成@Named,這里不再贅述。”,讓我突發(fā)奇想,能不能這樣用呢?
插一句題外話,guice入門資料,這里有一份整理好的,非常適合第一次接觸guice的朋友,推薦給大家:guice入門資料 ,我今天看的就是這個(gè)。
首先看思路,@Named是這樣用的:
binder.bindConstant().annotatedWith(named("count")).to(40);
binder.bindConstant().annotatedWith(named("color")).to("red");
似乎還沒(méi)有特別感覺(jué)是吧?換成這樣呢?binder.bindConstant().annotatedWith(named("color")).to("red");
binder.bindConstant().annotatedWith(named("username")).to("root");
binder.bindConstant().annotatedWith(named("password")).to("root");
看到username,password,總該熟悉了吧?配置啊配置,哪有不用配置文件的程序啊。binder.bindConstant().annotatedWith(named("password")).to("root");
提到配置文件,第一個(gè)想到的,當(dāng)然就是最原始的properties資源文件,相信類似這樣內(nèi)容的文件大家都見的多了:
username=root
password=root
ip=192.168.0.1
port=80
聯(lián)系一下@Named,有感覺(jué)了吧?properties資源文件的name、value對(duì),剛好對(duì)應(yīng).annotatedWith(named("color")).to("red");如果能把資源文件讀出來(lái),再按照name、value對(duì)用@Named綁定,不就實(shí)現(xiàn)了將properties資源文件中的配置信息綁定到運(yùn)用程序中了嗎?password=root
ip=192.168.0.1
port=80
先給出資源文件server.config.properties,內(nèi)容簡(jiǎn)單點(diǎn)意思一下:
server.ip=192.168.0.1
server.port=90
server.username=root
server.password=root
然后是java實(shí)現(xiàn)代碼,同樣簡(jiǎn)單意思一下而已:server.port=90
server.username=root
server.password=root
package test.hw.basic.demo.bindconstant;
import static com.google.inject.name.Names.named;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Properties;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.name.Named;
public class ConfigMain {
private static class Client {
@Inject
@Named("config.server.ip")
private String IP;
@Inject
@Named("config.server.port")
private int port;
@Inject
@Named("config.server.username")
private String username;
@Inject
@Named("config.server.password")
private String password;
public void work() {
System.out.println("ip=" + IP);
System.out.println("port=" + port);
System.out.println("username=" + username);
System.out.println("password=" + password);
//

}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new Module() {
@SuppressWarnings("unchecked")
public void configure(Binder binder) {
Properties p = new Properties();
try {
p.load(new InputStreamReader(this.getClass()
.getResourceAsStream("server.config.properties")));
} catch (IOException e) {
e.printStackTrace();
assert false;
}
Enumeration e = p.keys();
while(e.hasMoreElements()) {
String key = (String)e.nextElement();
String value = (String)p.get(key);
binder.bindConstant().annotatedWith(named("config." + key)).to(value);
}
}
});
Client client = injector.getInstance(Client.class);
client.work();
}
}
import static com.google.inject.name.Names.named;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.Properties;
import com.google.inject.Binder;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.name.Named;
public class ConfigMain {
private static class Client {
@Inject
@Named("config.server.ip")
private String IP;
@Inject
@Named("config.server.port")
private int port;
@Inject
@Named("config.server.username")
private String username;
@Inject
@Named("config.server.password")
private String password;
public void work() {
System.out.println("ip=" + IP);
System.out.println("port=" + port);
System.out.println("username=" + username);
System.out.println("password=" + password);
//


}
}
public static void main(String[] args) {
Injector injector = Guice.createInjector(new Module() {
@SuppressWarnings("unchecked")
public void configure(Binder binder) {
Properties p = new Properties();
try {
p.load(new InputStreamReader(this.getClass()
.getResourceAsStream("server.config.properties")));
} catch (IOException e) {
e.printStackTrace();
assert false;
}
Enumeration e = p.keys();
while(e.hasMoreElements()) {
String key = (String)e.nextElement();
String value = (String)p.get(key);
binder.bindConstant().annotatedWith(named("config." + key)).to(value);
}
}
});
Client client = injector.getInstance(Client.class);
client.work();
}
}
run一下,可以看到意料中的輸出:
ip=192.168.0.1
port=90
username=root
password=root
Ok,確認(rèn)無(wú)誤,我的想法得到了驗(yàn)證,這個(gè)思路是可行的。額外注意的是,port是int類型,guice非常機(jī)敏的完成了類型轉(zhuǎn)換,正確的注入了我們期望的int數(shù)據(jù)。port=90
username=root
password=root
上面的做法,適合類似用戶名密碼,ip端口這樣的幾乎是必須修改的配置信息,這些信息絕對(duì)不可能寫死在代碼里面。傳統(tǒng)的資源文件或者xml配置文件是存放它們最好的地方,而如何將這些配置信息傳入到以ioc,di為核心理念的應(yīng)用,以spring為例,比如有一個(gè)client bean要連接外部服務(wù)器需要注入ip,port信息,如果直接在applicationContext.xml文件中配置,毫無(wú)疑問(wèn)不是一個(gè)好辦法:太分散了,修改時(shí)找到要修改的地方可不容易,尤其對(duì)于bean比較多的情況而修改的人可能是客戶,現(xiàn)網(wǎng)施工維護(hù)人員,讓他們修改spring配置文件不現(xiàn)實(shí)。記得spring就有現(xiàn)成的完成讀取配置文件再注入bean的方案,細(xì)節(jié)大家可以google一下,比較簡(jiǎn)單好用。
guice剛開始學(xué)習(xí),似乎沒(méi)有找到類似spring的方法,如果真沒(méi)有官方現(xiàn)成的,那么上面的做法無(wú)疑是一條可行的解決方案。
posted on 2008-08-22 23:54 sky ao 閱讀(4241) 評(píng)論(3) 編輯 收藏 所屬分類: spring & IOC