|
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2008-03-22
ajoo 写道 我不知道为什么guice不能用在“企业”应用上。我们组大家对抛弃spring都欢欣鼓舞地。
guice的问题嘛,自然有。不过你要是没用过的话,也不容易讲明白。而且,等2.0出来,很多问题可能就解决了。 能在这儿跟贴的,估计guice的sample多多少少都跑过,加上guice语法也很简单,所以估计算得上“入门”的水平还是比较容易达到的。我的思路是,让热爱guice的人(比如 ajoo)谈谈guice的缺点,是不是比不喜欢guice的说的更有价值些?不用担心大家看不懂,我想guice还没复杂到“深奥”的程度。 |
|
| 返回顶楼 | |
|
最后更新时间:2008-03-22
好吧,我说说1.0的一些不足吧(其实你这些要求并不合理,你试试让rod等人告诉你spring的缺陷?只怕人家马上就defensive起来)。
1。provider使用匿名类,语法相当烦琐。比如你要从spring移植出来,那些<bean>就会变成一堆provider,看起来并不清爽——虽然比xml清爽一点。为了解决这个问题,我实现了一个2.0将要出来的功能:provider method。比如,对这么一个provider:
bind(Foo.class).toProvider(new Provider<Foo>() {
@Inject Provider<Bar> barProvider;
@Inject Provider<Baz> bazProvider;
public Foo get() {
FooImpl impl = new FooImpl();
impl.setBar(barProvider.get());
impl.setBaz(bazProvider.get());
return impl;
}
});
改写成provider method语法就是:
@Provide
public Foo foo(Bar bar, Baz baz) {
FooImpl impl = new FooImpl();
impl.setBar(bar);
impl.setBaz(baz);
return impl;
}
这下清爽了。我们这个扩展不会开源(没什么意义),等2.0吧。 2。provider注入有个bug。如果容器找不到Bar,它不会抛异常,而是打印一个stack trace了事。2.0会解决这个问题的。 3。provider无法得知自己被绑定的key。比如,你想在系统里面注入Bigtable。每个Bigtable都有一个名字,这个名字我们希望可以通过property来注入:
@Provide @ForFoo
public Bigtable fooBigtable(@Named("fooTable") String tableName) {
return BtUtil.createTable(tableName);
}
单独一个bigtable没问题。但是如果你系统里有七八个bigtable,那就要写七八个binding。很麻烦。理想情况是可以让provider知道自己被绑定在@Named("fooTable")上了,这样它可以直接向容器要求那个"fooTable"的property的值。结果就是你只需要一个provider:
bind(Bigtable.class).annotatedWith(Named.class).toProvider(new SuperProvider<Bigtable>() {
@Inject Injector injector;
public Bigtable get(Key<? super Bigtable> key) {
Key<String> tableNameKey = Key.get(String.class, Names.getName(key.getAnnotation());
String tableName = injector.getInstance(tableNameKey);
return BtUtil.createTable(tableName);
}
});
然后你就可以到处用"@Named("fooTable") Bigtable bigtable"来注入了。这个问题期望在2.0里能得到解决。 4。所谓的robot leg问题。就是说,Guice最擅长的是创建一个静态对象网络,也就是说,每个Key在任何时候任何上下文都只对应一个实现。但是有时候不是那么简单。 比如,我的系统是个分层的结构。A依赖B,B依赖C,C依赖D。好,Guice老老实实地把对象网络建立好了。现在,我要出妖蛾子了,我的D要根据当前request的客户browser类型来变化,比如对IE,我用IE_D,对FF用FF_D。好了,现在麻烦了,我要弄一个@ForIe和一个@ForFf的annotation,这倒也没什么,但是我现在要把C也分裂成@ForIe的C和@ForFf的C,还要分裂B,还有A。这样我就可以在最外层的action里面这么写:
class MyAction {
private final A forIe;
private final A forFf;
@Inject public MyAction(@ForIe A forIe, @ForFf A forFf) {
...
}
public void run() {
if (isIe()) {
forIe.run();
} else {
forFf.run();
}
}
}
但是module的复杂度一下子提升上去了。 对这个问题目前七嘴八舌有很多解决方法的提议。我喜欢Brian Slensinskey的提议,就是说,允许Injector在动态改变binding。然后在Guice核心支持所谓客户自定义工厂的概念。这样不但能解决robot leg问题,还可以解决Provider的侵入性问题。我们可以自己定义自己的Factory, Getter,而不是有时候被邪恶诱惑使用容器提供的Provider接口。 5。Guice不支持组合不同的binding annotation。比如,我如果有两把铁锹,一个是用来铲雪的,一个用来挖地的,好办,我可以写两个annotation,@ForSnowShovelling, @ForDigging。但是如果回头我发现有另外一个维度,比如便宜的和贵的,我即使可以弄两个@Expensive, @Cheap,我也没办法用组合@Cheap @ForSnowShovelling来表达“便宜的雪铲”这个概念。我只能写@CheapForSnowShovelling。:-( 6。你可以注射List<String>, List<Integer>, List<Map<String, Iterable<Object>>>,都行,但是,不能注射List<T>,不能注射List<? extends Closeable>。也就是说,不支持wildcard,并且类型参数必须是具体的,而不是T。 7。Guice的fluent interface api用起来还成。但是mock测试起来(写扩展的时候,不是应用)比较麻烦,看javadoc也比较复杂,要看那一堆名字好长好长的中间Builder对象的文档。 8。没有lifecycle,至少destroy或者PreDestroy还是有用的。 大致就想到这么多。 |
|
| 返回顶楼 | |
|
最后更新时间:2008-03-23
ajoo 写道 好吧,我说说1.0的一些不足吧(其实你这些要求并不合理,你试试让rod等人告诉你spring的缺陷?只怕人家马上就defensive起来)。
1。provider使用匿名类,语法相当烦琐。比如你要从spring移植出来,那些<bean>就会变成一堆provider,看起来并不清爽——虽然比xml清爽一点。为了解决这个问题,我实现了一个2.0将要出来的功能:provider method。比如,对这么一个provider:
bind(Foo.class).toProvider(new Provider<Foo>() {
@Inject Provider<Bar> barProvider;
@Inject Provider<Baz> bazProvider;
public Foo get() {
FooImpl impl = new FooImpl();
impl.setBar(barProvider.get());
impl.setBaz(bazProvider.get());
return impl;
}
});
改写成provider method语法就是:
@Provide
public Foo foo(Bar bar, Baz baz) {
FooImpl impl = new FooImpl();
impl.setBar(bar);
impl.setBaz(baz);
return impl;
}
这下清爽了。我们这个扩展不会开源(没什么意义),等2.0吧。 2。provider注入有个bug。如果容器找不到Bar,它不会抛异常,而是打印一个stack trace了事。2.0会解决这个问题的。 3。provider无法得知自己被绑定的key。比如,你想在系统里面注入Bigtable。每个Bigtable都有一个名字,这个名字我们希望可以通过property来注入:
@Provide @ForFoo
public Bigtable fooBigtable(@Named("fooTable") String tableName) {
return BtUtil.createTable(tableName);
}
单独一个bigtable没问题。但是如果你系统里有七八个bigtable,那就要写七八个binding。很麻烦。理想情况是可以让provider知道自己被绑定在@Named("fooTable")上了,这样它可以直接向容器要求那个"fooTable"的property的值。结果就是你只需要一个provider:
bind(Bigtable.class).annotatedWith(Named.class).toProvider(new SuperProvider<Bigtable>() {
@Inject Injector injector;
public Bigtable get(Key<? super Bigtable> key) {
Key<String> tableNameKey = Key.get(String.class, Names.getName(key.getAnnotation());
String tableName = injector.getInstance(tableNameKey);
return BtUtil.createTable(tableName);
}
});
然后你就可以到处用"@Named("fooTable") Bigtable bigtable"来注入了。这个问题期望在2.0里能得到解决。 4。所谓的robot leg问题。就是说,Guice最擅长的是创建一个静态对象网络,也就是说,每个Key在任何时候任何上下文都只对应一个实现。但是有时候不是那么简单。 比如,我的系统是个分层的结构。A依赖B,B依赖C,C依赖D。好,Guice老老实实地把对象网络建立好了。现在,我要出妖蛾子了,我的D要根据当前request的客户browser类型来变化,比如对IE,我用IE_D,对FF用FF_D。好了,现在麻烦了,我要弄一个@ForIe和一个@ForFf的annotation,这倒也没什么,但是我现在要把C也分裂成@ForIe的C和@ForFf的C,还要分裂B,还有A。这样我就可以在最外层的action里面这么写:
class MyAction {
private final A forIe;
private final A forFf;
@Inject public MyAction(@ForIe A forIe, @ForFf A forFf) {
...
}
public void run() {
if (isIe()) {
forIe.run();
} else {
forFf.run();
}
}
}
但是module的复杂度一下子提升上去了。 对这个问题目前七嘴八舌有很多解决方法的提议。我喜欢Brian Slensinskey的提议,就是说,允许Injector在动态改变binding。然后在Guice核心支持所谓客户自定义工厂的概念。这样不但能解决robot leg问题,还可以解决Provider的侵入性问题。我们可以自己定义自己的Factory, Getter,而不是有时候被邪恶诱惑使用容器提供的Provider接口。 5。Guice不支持组合不同的binding annotation。比如,我如果有两把铁锹,一个是用来铲雪的,一个用来挖地的,好办,我可以写两个annotation,@ForSnowShovelling, @ForDigging。但是如果回头我发现有另外一个维度,比如便宜的和贵的,我即使可以弄两个@Expensive, @Cheap,我也没办法用组合@Cheap @ForSnowShovelling来表达“便宜的雪铲”这个概念。我只能写@CheapForSnowShovelling。:-( 6。你可以注射List<String>, List<Integer>, List<Map<String, Iterable<Object>>>,都行,但是,不能注射List<T>,不能注射List<? extends Closeable>。也就是说,不支持wildcard,并且类型参数必须是具体的,而不是T。 7。Guice的fluent interface api用起来还成。但是mock测试起来(写扩展的时候,不是应用)比较麻烦,看javadoc也比较复杂,要看那一堆名字好长好长的中间Builder对象的文档。 8。没有lifecycle,至少destroy或者PreDestroy还是有用的。 大致就想到这么多。 第四点貌似可以用scope+proxy来解决 |
|
| 返回顶楼 | |
|
最后更新时间:2008-03-23
在Spring 2.5发布这么久以后,还进行这样的讨论,真是让人费解。
|
|
| 返回顶楼 | |
|
最后更新时间:2008-03-23
都08年了,还有人谈Spring这么古老的东西,真是让人费解。
|
|
| 返回顶楼 | |
|
最后更新时间:2008-03-24
偶觉得国内比国外落后个几年很正常的...落后一个世纪都可以呢,何况是几年?
|
|
| 返回顶楼 | |
|
最后更新时间:2008-03-24
ajoo 写道 都08年了,还有人谈Spring这么古老的东西,真是让人费解。
呵呵, 好像变化是挺快的, 现在都不大讨论Hibernate, Spring 这些东东了. |
|
| 返回顶楼 | |
|
最后更新时间:2008-03-24
icess 写道 ajoo 写道 都08年了,还有人谈Spring这么古老的东西,真是让人费解。
呵呵, 好像变化是挺快的, 现在都不大讨论Hibernate, Spring 这些东东了. 我在2003年3月就开始谈Hibernate,2003年11月就开始谈Spring。我都嚼来嚼去嚼了五年了,你还要逼我再谈spring/hibernate,还是饶了我吧。 |
|
| 返回顶楼 | |
|
最后更新时间:2008-03-24
谈Spring的时候,EJB的卫道士们反对
谈Guice了,Spring的卫道士们反对. 历史总是惊人地相似. |
|
| 返回顶楼 | |
|
最后更新时间:2008-03-24
blogbin 写道 java领域同类的东西太多,而不是太少,大量的精力都花在选择哪个框架。
搞不好,几年之后,guice也和现在spring一样臃肿不堪。 你花大量的精力选框架???真是闲啊. |
|
| 返回顶楼 | |












