<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>neuzhujf</title>
    <description></description>
    <link>http://neuzhujf.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>好文共享：Guice与Spring框架的区别（转）</title>
        <author>neuzhujf</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://neuzhujf.javaeye.com">neuzhujf</a>&nbsp;
          链接：<a href="http://neuzhujf.javaeye.com/blog/170522" style="color:red;">http://neuzhujf.javaeye.com/blog/170522</a>&nbsp;
          发表时间: 2008年03月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><img src="C:\Documents and Settings\shuku\デスクトップ\a.bmp" border="0" height="1" alt="" width="1" /></p><p>依赖注入，DI（Dependency Injection），它的作用自然不必多说，提及DI容器，例如spring，picoContainer，EJB容器等等，近日，google诞生了更轻巧的DI容器&hellip;&hellip;Guice! <br />废话不多讲了，先看看Guice是如何实现注入的吧。 <br />定义一个简单的service接口和它的实现吧： <br /><br /></p><pre name="code" class="java">public interface MyService ...{
    void myMethod();
}

public class MyServiceImpl implements MyService ...{
    public void myMethod() ...{
        System.out.println(&quot;Hello,World!&quot;);
    }
}
</pre><br /><br />以上是最普通的接口和其实现，没什么可说的。 <br />定义一个测试类,这个类里边包括service对象的一个引用，这个对象是需要Guice进行注入的 <br /><br /><br /><pre name="code" class="java">import com.google.inject.Inject;
public class Client ...{
    MyService service;
    @Inject //告诉容器，这里的service对象的引用,需要进行注入
    void setService(MyService service) ...{ //这里的方法名字可以任意定义
        this.service = service;
    }
    public void myMethod() ...{
        service.myMethod();
    }
}
</pre><br /><br />这里除了加了一个@Inject,和Spring的配置没有任何的区别，@Inject，是表示对容器说，这里的service需要注射，等到运行的时候，容器会拿来一个实例给service，完成注射的过程。 <br /><br />定义Guice的Module文件 告诉容器如何进行注入 <br /><br /><br /><pre name="code" class="java">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定义的对象，而且这个对象是单例的。
    }
}
</pre><br /><br />创建测试类 <br /><br /><br /><pre name="code" class="java">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();    
}
}
</pre><br /><br />运行测试类，控制台输出：Hello,World! <br />完成注入过程 <br /><br />下面看看Guice还有哪些其它的使用特性。 <br />1，如果在实现你确定MyService定义的对象，就要被注射为MyServiceImpl而不是其它的实现类的话，可以在MyService接口加上@ImplementedBy(MyServiceImpl.class) <br /><br /><br /><br /><pre name="code" class="java">import com.google.inject.ImplementedBy;

@ImplementedBy(MyServiceImpl.class)
//我总觉得这样有点背离了依赖注入的初衷了
public interface MyService ...{
    void myMethod();
}
</pre><br /><br />这样的话，在MyModule里的configure方法中就可以不加任何东西，容器就会自动注射给MyServiceImpl对象。 <br /><br />2，可以对Field进行注解式注入 <br />在Client.java中也可以把这个@Inject标注在MyService service;的前边，如：@Inject MyService service; <br /><br /><br />3，可使用自定义Annotation标注。 <br /><br /><br /><pre name="code" class="java">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 })
@BindingAnnotation
public @interface MyInterface ...{
    
}
</pre><br /><br />那么Client.java需要改为 <br /><br /><br /><pre name="code" class="java">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();
    }
}
</pre><p><br /><br />MyModule.java中的configure方法内容需改为: <br /><br />binder.bind(MyService.class).annotatedWith(MyInterface.class).to( <br />MyServiceImpl.class).in(Scopes.SINGLETON); <br />意思是说对于标注为MyInterface的MyService定义的对象进行注入 <br /><br />进行Annotation标注的成员（Field,method,argument等）进行自定义Annotation标注，该成员既拥有该属性，可以在运行，根据这些成员的不同属性，做一些不同的事情 例如：spring的AspectJ，xdoclet等都是如此。 <br /><br /><br /><br />再借斧子的例子说一说spring与guice的区别 <br />看下边对于不同社会形态下一个人（java对象，调用者）需要一把斧子（java对象，被调用者）的例子： <br />（1），原始社会时，劳动社会基本没有分工，需要斧子的人（调用者）只好自己去磨一把斧子，每个人拥有自己的斧子，如果把大家的石斧改为铁斧，需要每个人都要学会磨铁斧的本领，工作效率极低。 <br />对应Java里的情形是：java程序里的调用者new一个被调用者的实例。类耦合度极高，修改维护烦琐，效率极低。 <br />（2），工业社会时，工厂出现，斧子不再由普通人完成，而由工厂生产，当人们需要斧子的时候，可以到工厂购买斧子，无需关心斧子是怎么制造出来的，如果废弃铁斧为钢斧，只需改变工厂的制造工艺即可，制作工艺是工厂决定的，工厂生产什么斧子，工人们就得用什么斧子。 <br />对应的Java里的情形是：Java程序的调用者可以以来简单工厂创建被调用者，变化点被隔离到了简单工厂里，虽然耦合度降低，但是调用者会和工厂耦合，而且需要定位自己的工厂。 <br />（3）近代工业社会，工厂蓬勃发展，人们需要什么斧子，只需要提供一个斧子图形，商家会按照你提供的图形将你的斧子订做好，送上门。 <br />对应Java里的情形：spring的依赖注入 <br />（4）进入按需要分配社会，信息进入现代化，人们不再去工厂购买斧子，不再拘泥于需要什么斧子事先画好什么样的图形，只需要打个电话，描述一下需要什么类型的斧子，或许想打造一个物美价廉的斧子，商家会根据市场零件的价格，计算出最优制作工艺,打造最适合的斧子送过来，更加信息化，更加人性化。 <br />对应Java里的情形：基于描述的注入，动态的，灵活简单的注入，如：Guice。 <br /><br />对于该不该使用Guice,我想也是仁者见仁,智者见智,就象好多论坛里动不动有人会在那里讨论到底学Java还是学.net或者是使用eclipse还是Jbuilder的这类无聊话题,适合和满足项目需求的,又能省工省力简单的完成工作的,就是最好的。 </p><p>&nbsp;</p><table cellspacing="1" border="1" summary="Guice VS Spring" style="font-size: 10pt" width="100%" cellpadding="1"><caption>Guice与Spring的对比</caption><tbody><tr><td>&nbsp;</td><td>Spring</td><td>Guice</td></tr><tr><td>使用XML</td><td>使用将类与类之间的关系隔离到xml中，由容器负责注入被调用的对象，因此叫做依赖注入</td><td>不使用xml,将类与类之间的关系隔离到Module中，声名何处需要注入，由容器根据Module里的描述，注入被调用的对象。</td></tr><tr><td>使用Annotation</td><td>&nbsp;</td><td>使用<br />支持自定义Annotation标注，对于相同的接口定义的对象引用，为它们标注上不同的自定义Annotation注释，就可以达到同一个类里边的同一个接口的引用，注射给不同的实现，在Module里用标注做区分，灵活性大大增加。<br />使用Annotation也未必是好事，范型等新特性也未必是好事，目前大多的<a href="http://server.chinaitlab.com/" class="channel_keylink" target="_blank"><span style="font-size: small">服务器</span></a>均不支持jdk1.5,wls要9以前才支持，而目前的客户由于价格原因也很少选用wls9的，至少我们做过的项目中都没有。功能再强，客户不需要，何用？<br /></td></tr><tr><td>运行效率</td><td>装载spring配置文件时，需解析xml，效率低，getBean效率也不高，不过使用环境不会涉及到getBean，只有生产环境的时候会用到getBean,在装载spring应用程序的时候，已经完成全部的注射，所以这个低效率的问题不是问题。</td><td>使用Annotation，cglib, 效率高与spring最明显的一个区别，spring是在装载spring配置文件的时候把该注入的地方都注入完，而Guice呢，则是在使用的时候去注射，运行效率和灵活性高。<br /></td></tr><tr><td>类耦合度</td><td>耦合度低，强调类非侵入，以外部化的方式处理依赖关系，类里边是很干净的，在配置文件里做文章，对类的依赖性极低。</td><td>高，代码级的标注，DI标记@inject侵入代码中，耦合到了类层面上来，何止侵入，简直侵略，代码耦合了过多guice的东西，大大背离了依赖注入的初衷，对于代码的可维护性，可读性均不利</td></tr><tr><td>类编写时</td><td>需要编写xml，配置Bean，配置注入</td><td>只需声明为@inject,等着被注入，<br />最后在统一的Module里声明注入方式<br /></td></tr><tr><td>仅支持IOC</td><td>否，spring目前已经涉猎很多部分</td><td>是，目前仅仅是个DI容器</td></tr><tr><td>是否易于代码重构</td><td>统一的xml配置入口，更改容易</td><td>配置工作是在Module里进行，和spring异曲同功</td></tr><tr><td>支持多种注入方式</td><td>构造器，setter方法</td><td>Field,构造器，setter方法</td></tr><tr><td>灵活性</td><td>&nbsp;</td><td><p>1,如果同一个接口定义的引用需要注入不同的实现，就要编写不同的Module，烦琐</p><p>2,动态注入</p><p>如果你想注射的一个实现，你还未知呢，怎么办呢，spring是没办法，事先在配置文件里写死的，而Guice就可以做到，就是说我想注射的这个对象我还不知道注射给谁呢，是在运行时才能得到的的这个接口的实现，所以这就大大提高了依赖注射的灵活性，动态注射。</p></td></tr><tr><td>与现有框架集成度</td><td>1，&nbsp;高，众多现有优秀的框架（如struts1.x等）均提供了spring的集成入口，而且spring已经不仅仅是依赖注入，包括众多方面。<br />2，&nbsp;Spring也提供了对Hibernate等的集成，可大大简化开发难度。<br />3，&nbsp;提供对于orm,rmi,webservice等等接口众多，体系庞大。<br /></td><td>1，可以与现有框架集成，不过仅仅依靠一个效率稍高的DI，就想取代spring的地位，有点难度。</td></tr><tr><td>配置复杂度</td><td>在xml中定位类与类之间的关系,难度低</td><td>代码级定位类与类之间的关系,难度稍高</td></tr></tbody></table><br />原文：<a href="http://java.chinaitlab.com/Spring/719816.html" target="_blank">http://java.chinaitlab.com/Spring/719816.html</a> <p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://neuzhujf.javaeye.com/blog/170522#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 12 Mar 2008 14:04:52 +0800</pubDate>
        <link>http://neuzhujf.javaeye.com/blog/170522</link>
        <guid>http://neuzhujf.javaeye.com/blog/170522</guid>
      </item>
  </channel>
</rss>