控制反轉的缺失部分是應用程序層不直接調用構造函數。它使用工廠(IoC容器)來填充構造函數參數。
無論使用何種工具,吉斯/春/ PicoContainer的/單,工廠,你的應用程序代碼應該是這個樣子:
@Controller
class MyController {
@Resource // Some container knows about this annotation and wires you in
MyBusinessLogic myBusinessLogic;
@RequestMethod("/foo/bar.*")
public MyWebResponse doService(Response resp, long id, String val) {
boolean worked = myBusinessLogic.manipulatevalue(id, val);
return new MyWebResponse(worked);
}
}
注意,myBusinessLogic可以以多種方式註冊 - Java的@Resource,MyBusinessLogicFactory .getMyBusinessLogic(),guice.get(MyBusinessLogic.class)等
甲差芒的解決辦法是:
package foo;
class MyBusinessLogicFactory {
static volatile MyBusinessLogic instance; // package-scoped so unit tests can override
public static MyBusinessLogic getInstance() {
if (instance == null) {
synchronized(MyBusinessLogicFactory.class) {
instance = new MyBusinessLogic(MyDatabaseLayerFactory.getInstance());
}
}
return instance;
}
}
// repeat with MyDatabaseLayerFactory
注第因爲它沒有範圍,所以以上單例模型是非常不鼓勵的。你可以換上述上下文裏 - soething像
class Context {
Map<Class,Object> class2Instance = new ConcurrentHashMap<>();
public <T> T getInstance(Class<T> clazz) {
Object o = class2Instance.get(clazz);
if (o == null) {
synchronized(this) {
o = class2Instance.get(clazz);
if (o != null) return (T)o;
o = transitivelyLoadInstance(clazz); // details not shown
for (Class c : loadClassTree(clazz)) { // details not shown
class2Instance.put(c, o);
}
}
}
return (T)o;
}
...
}
但在這一點上,PicoContainer的,Guice和彈簧可以解決上述的複雜SOOO好得多。另外,像java這樣的符合java 6註解的spring這樣的東西,意味着除了構造函數注入之外,你可以做其他事情,如果你有多個相同基本數據類型的配置項(例如字符串),這非常有用。
是的,我有接口。我只是用這個例子來簡化事情。你能指點我一些複雜例子的參考嗎? – zengr
我會看看Guice [用戶指南](http://code.google.com/p/google-guice/wiki/Motivation),包括綁定,範圍,擴展等方面的東西。 – ColinD
Btw,我正在處理一些遺留代碼,我無法爲MyDatabaseLayer提供接口。從Guice的角度來看這會是一個問題嗎? – zengr