好文共享:Guice与Spring框架的区别(转)
依赖注入,DI(Dependency Injection),它的作用自然不必多说,提及DI容器,例如spring,picoContainer,EJB容器等等,近日,google诞生了更轻巧的DI容器……Guice!
废话不多讲了,先看看Guice是如何实现注入的吧。
定义一个简单的service接口和它的实现吧:
public interface MyService ...{ void myMethod();}public class MyServiceImpl implements MyService ...{ public void myMethod() ...{ System.out.println("Hello,World!"); }}import com.google.inject.Inject;public class Client ...{ MyService service; @Inject //告诉容器,这里的service对象的引用,需要进行注入 void setService(MyService service) ...{ //这里的方法名字可以任意定义 this.service = service; } public void myMethod() ...{ service.myMethod(); }}import com.google.inject.Binder;import com.google.inject.Module;import com.google.inject.Scopes;public class MyModule implements Module ...{ public void configure(Binder binder) ...{ binder.bind(MyService.class).to(MyServiceImpl.class).in(Scopes.SINGLETON); // 这句代码的意思是说:运行时动态的将MyServiceImpl对象赋给MyService定义的对象,而且这个对象是单例的。 }}import com.google.inject.Guice;import com.google.inject.Injector;public class Test ...{ public static void main(String[] args) ...{MyModule module = new MyModule();// 定义注射规则Injector injector = Guice.createInjector(module);// 根据注射规则,生成注射者 Client client = new Client();injector.injectMembers(client);// 注射者将需要注射的bean,按照规则,把client这个客户端进行注射 client.myMethod(); }}import com.google.inject.ImplementedBy;@ImplementedBy(MyServiceImpl.class)//我总觉得这样有点背离了依赖注入的初衷了?public interface MyService ...{ void myMethod();}package mypackage;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import com.google.inject.BindingAnnotation;@Retention(RetentionPolicy.RUNTIME)@Target( ...{ ElementType.FIELD, ElementType.PARAMETER })@BindingAnnotationpublic @interface MyInterface ...{ }package mypackage;import com.google.inject.Inject;public class Client ...{ @Inject @MyInterface MyService service; void setService(MyService service) ...{ // 这里的方法名字可以任意定义 this.service = service; } public void myMethod() ...{ service.myMethod(); }}
MyModule.java中的configure方法内容需改为:
binder.bind(MyService.class).annotatedWith(MyInterface.class).to(
MyServiceImpl.class).in(Scopes.SINGLETON);
意思是说对于标注为MyInterface的MyService定义的对象进行注入
进行Annotation标注的成员(Field,method,argument等)进行自定义Annotation标注,该成员既拥有该属性,可以在运行,根据这些成员的不同属性,做一些不同的事情? 例如:spring的AspectJ,xdoclet等都是如此。
再借斧子的例子说一说spring与guice的区别
看下边对于不同社会形态下一个人(java对象,调用者)需要一把斧子(java对象,被调用者)的例子:
(1),原始社会时,劳动社会基本没有分工,需要斧子的人(调用者)只好自己去磨一把斧子,每个人拥有自己的斧子,如果把大家的石斧改为铁斧,需要每个人都要学会磨铁斧的本领,工作效率极低。
对应Java里的情形是:java程序里的调用者new一个被调用者的实例。类耦合度极高,修改维护烦琐,效率极低。
(2),工业社会时,工厂出现,斧子不再由普通人完成,而由工厂生产,当人们需要斧子的时候,可以到工厂购买斧子,无需关心斧子是怎么制造出来的,如果废弃铁斧为钢斧,只需改变工厂的制造工艺即可,制作工艺是工厂决定的,工厂生产什么斧子,工人们就得用什么斧子。
对应的Java里的情形是:Java程序的调用者可以以来简单工厂创建被调用者,变化点被隔离到了简单工厂里,虽然耦合度降低,但是调用者会和工厂耦合,而且需要定位自己的工厂。
(3)近代工业社会,工厂蓬勃发展,人们需要什么斧子,只需要提供一个斧子图形,商家会按照你提供的图形将你的斧子订做好,送上门。
对应Java里的情形:spring的依赖注入
(4)进入按需要分配社会,信息进入现代化,人们不再去工厂购买斧子,不再拘泥于需要什么斧子事先画好什么样的图形,只需要打个电话,描述一下需要什么类型的斧子,或许想打造一个物美价廉的斧子,商家会根据市场零件的价格,计算出最优制作工艺,打造最适合的斧子送过来,更加信息化,更加人性化。
对应Java里的情形:基于描述的注入,动态的,灵活简单的注入,如:Guice。
对于该不该使用Guice,我想也是仁者见仁,智者见智,就象好多论坛里动不动有人会在那里讨论到底学Java还是学.net或者是使用eclipse还是Jbuilder的这类无聊话题,适合和满足项目需求的,又能省工省力简单的完成工作的,就是最好的。
?
Guice与Spring的对比?SpringGuice使用XML使用将类与类之间的关系隔离到xml中,由容器负责注入被调用的对象,因此叫做依赖注入不使用xml,将类与类之间的关系隔离到Module中,声名何处需要注入,由容器根据Module里的描述,注入被调用的对象。使用Annotation?使用1,如果同一个接口定义的引用需要注入不同的实现,就要编写不同的Module,烦琐
2,动态注入
如果你想注射的一个实现,你还未知呢,怎么办呢,spring是没办法,事先在配置文件里写死的,而Guice就可以做到,就是说我想注射的这个对象我还不知道注射给谁呢,是在运行时才能得到的的这个接口的实现,所以这就大大提高了依赖注射的灵活性,动态注射。
与现有框架集成度1,?高,众多现有优秀的框架(如struts1.x等)均提供了spring的集成入口,而且spring已经不仅仅是依赖注入,包括众多方面。?
1 楼 neuzhujf 2008-03-12 <h1>Guice和JavaConfig:使用Annotation进行反转控制的两种方式</h1><p class='info'>作者 <strong>Rob Thornton</strong>译者 <strong>Jason Lai</strong> 发布于 2007年3月27日 下午3时30分 </p><dl class='tags2'><dt class='community'>社区 </dt><dd><a name='java' href='http://www.infoq.com/cn/java' id='739'>Java</a> </dd><dt class='topics'>主题 </dt><dd><a name='artifacts_tools' href='http://www.infoq.com/cn/artifacts_tools' id='781'>工件和工具</a> </dd></dl><p>随着 <a href='http://code.google.com/p/google-guice/'>Guice</a> 的最初发行版慢慢尘埃落定,将它和 <a href='http://www.springframework.org/'>Spring IoC</a>,尤其是和 <a href='http://www.springframework.org/javaconfig'>Spring JavaConfig</a> 进行的比较也随之浮出水面。Guice 和 JavaConfig 采取了两种不同的方式使用 Java Annotations 将 IoC 配置放入代码。</p><p>目前 Spring JavaConfig 发布了 1.0 Milestone 1 版本,它和 Guice 的基本想法是一致的——把配置从 XML 移至 Annotation 是一种更好的做法,因为这样使得配置信息与代码更为紧密。<a href='http://tapestry.apache.org/tapestry5/tapestry-ioc/'>Tapestry 的 IoC 容器</a>也是根据同样的想法设计的。</p><p>JavaConfig 和 Guice 的背景极其相似。事实上,Bob Lee 是这样叙述它们的历史的:</p><blockquote>此外,我还想说一个有点意思的小故事:Guice 最开始的时候和 Spring JavaConfig 看起来非常像——这并不奇怪,因为 Rod 一年前向我展示了 Spring JavaConfig(而六个月前我又让他看了 Guice)。正如使用 JavaConfig 一样,你得显式地写 Java 代码来连接你的对象。我从一开始就引入 @Inject 做为检查外部代码按照你的安排调用所有的 setters 的一种可选方式。而自打我们有了 @Inject,我开始问,我们为什么还需要显式地编写对象连接代码呢?于是很快我们就有大家今天所知道的 Guice。<br/></blockquote><p>?关于 Guice 和 JavaConfig 区别的<a href='http://codecurl.wordpress.com/2007/03/21/not-convinced-about-guice-spring-scores-again-with-javaconfig/'>帖子</a>有<a href='http://jroller.com/page/habuma?entry=guice_vs_spring_javaconfig_a'>不少</a>。Debasish Ghosh 恰如其分地<a href='http://debasishg.blogspot.com/2007/03/using-guice-as-di-framework-some.html'>总结到</a>:</p><blockquote><p>Guice 和 Spring 之间最主要的区别,可以归结为它们看待依赖关系和配置的哲学之间的差异。Spring 宣扬的是非侵入性的方式,以一种完全外部化的方式来对待对象依赖关系。在 Spring 里,你可以使用 XML、Spring JavaConfig 或者 Groovy-Spring DSL 来连接对象依赖关系,也可以使用其它的方案,如 Spring-annotations。但是,不管你用的是什么技术,依赖关系总是被外部化的。 </p><p>另一方面,Guice 却把配置做为你的应用程序模型的首要对象来看待,允许它们存在于你的领域模型代码中。我们使用 Guice 模块来说明需要注入什么东西,然后使用 annotations 来指明需要在什么注入。你可以使用注入来标记(annotate)类本深(通过 @Inject annotation)。缺点则是(如果你使者么认为的话)你必须在你的领域模型中引入 com.google.inject.*。但它通过元数据编程(metadata programming)来确保了目标的方向性,以及注入的显式语义。</p></blockquote><p>在这些文章的回帖中,你可以发现,在这两个框架之间做选择的时候,最值得注意的就是它们设计哲学的区别。你会希望依赖注入和代码靠得有多近呢?如果使用 Guice,你的代码将和容器紧密耦合在一起,这样做有些人喜欢,有些人反感。Guice 号称自己的速度更快,但值得注意的是,Spring IoC 容器(不管是 JavaConfig 还是其它)支持多种钩子,而 Guice 并没有提供。Spring 为大家带来的不仅仅是 IoC,而 Guice 并不打算解决那些大问题。</p>