Guice -- 可替代Spring的轻量级DI框架

<h1>Guice -- 可替代Spring的轻量级DI框架</h1>
<h2>什么是Guice?</h2>
<h1>“</h1>
<p>Guice让你的Java代码摆脱了Factory以及New的使用。我们可以认为Guice的@Inject是一个新的New方法。Guice充分的利用Java类型安全的本质,特别是在Java5中例如泛型以及注解的特性。你可以认为Guice是来弥补核心java里所缺失的特性的,理想状态下,Java本身将会提供大部分这些特性,但是在这之前,我们可以用Guice来达到相同效果。</p>
<h1>”</h1>
<p>如果你使用过Spring或者其他DI框架,那么你应该对上面的概念很熟悉。下面我将会在这篇文章中介绍如何在一个非Web应用中使用Guice。今后我会陆续介绍Web应用中Guice的使用。</p>
<h1>Guice比Spring好吗?</h1>
<p>额。。这个话题将会是永远都讨论不完的,就像:EJB vs Spring , Strust VS JSF 等。其实这只是选择的问题。不过我可以这么说:如果你仅仅是需要在你的应用中添加DI,那么就使用Guice吧,它是一个轻量级的,类型安全且速度比Spring快的DI框架。</p>
<h2>在非Web应用中使用Guice</h2>
<p>假设现在你有一个应用,包含着Main方法的类名叫做Application。如果想要使用Guice的话,那么我们需要改变一下常规的方法,在启动应用的同时,我们还需要触发依赖注入。为了达到这样一个目的,你必须有一个入口点来触发那些需要被注入的对象。在注入完成之后,才能开始启动实际的应用逻辑。</p>
<p>我们将负责以上工作逻辑的类叫做BootStrap类。同时我们需要继承AbstractModule类来创建一个Module。在Java文档中对Module接口的定义是这样的:</p>
<h1>“</h1>
<p>一个Module使用来构建配置信息的,通常是对于用来创建Injector接口的绑定的配置信息。一个基于Guice最终是由多个Modules集合以及一些BootStrap代码所组合而成的</p>
<h1>”</h1>
<p>让我们来看一看代码:</p>
<h2>BootStrap 类</h2>
<pre><code>package com.insidecoding.guice;
import com.google.inject.Guice;

import com.google.inject.Injector;
/**
 * Bootstrap class that creates the root object that triggers the graph of
 * objects creation and injection
 */
public class Bootstrap {
public static void main(String[] args) {
 Injector injector = Guice.createInjector(new MyModule());
 IApplication app = injector.getInstance(IApplication.class);
 app.start();
 }
}
</code></pre>

<h2>IApplication 接口</h2>
<pre><code>package com.insidecoding.guice;
public interface IApplication {
 /**
 * Starts the current application
 */
 void start();
}
</code></pre>

<h2>Application 类</h2>
<pre><code>package com.insidecoding.guice;

import com.google.inject.Inject;

public class Application implements IApplication {
@Inject
 private IPrintingService ip;
public void start() {
 ip.print("Hello from guice");
 }
}
</code></pre>

<p>假设现在你的应用逻辑是这样的:使用IPrintServer来答应一条String,这个Printing Server将会使用ICaching Service来缓存这条String。这些Service的实现将会有在应用中的Guice来注入。单独的ICachingService的实现类。</p>
<h2>IPrintingService接口</h2>
<pre><code>package com.insidecoding.guice;
import com.google.inject.ImplementedBy;

@ImplementedBy(PrintingService.class)
public interface IPrintingService {
/**
 * Prints a string
 * @param s
 */
 void print(String s);
}
</code></pre>

<h2>PrintingService类</h2>
<pre><code>package com.insidecoding.guice;

import javax.inject.Inject;

public class PrintingService implements IPrintingService {

    @Inject
    private ICachingService cs;

    @Override
    public void print(String s) {
        System.out.println(s);
        cs.cacheIt(s);
    }

}
</code></pre>

<h2>ICachingService类</h2>
<pre><code>package com.insidecoding.guice;

import com.google.inject.ImplementedBy;

@ImplementedBy(CachingService.class)
public interface ICachingService {

    /**
     * Caches a String
     * @param s
     */
    void cacheIt(String s);
}
</code></pre>

<h2>CachingService类</h2>
<pre><code>package com.insidecoding.guice;

public class CachingService implements ICachingService {

    @Override
    public void cacheIt(String s) {
        System.out.println("Caching: " + s);
    }

}
</code></pre>

<h2>MyModule类</h2>
<p>package com.insidecoding.guice;</p>
<p>import com.google.inject.AbstractModule;</p>
<p>public class MyModule extends AbstractModule {</p>
<p>@Override
   protected void configure() {
  bind(IApplication.class).to(Application.class);
   }
}
这些代码都非常简单而且直接,要让这些代码可以运行期来,你还需要从Guice发布版中添加几个Jar文件。
-aopalliance.jar</p>
<ul>
<li>
<p>guice-3.0.jar</p>
</li>
<li>
<p>javax.inject.jar</p>
</li>
</ul>
<p>如果你看的仔细一点的话,你会在注入这块地放发现一些不同:在Application类中使用的是<code>com.google.inject.Inject</code> 注解,而在PrintingService类中使用的却是<code>javax.inject.Inject</code>注解。这是应为Guice 3.0是与JSR-330兼容的,然后将它们两个混合使用时不鼓励的,所以还是尽量使用Guice的@Inject注解吧。</p>
<h1>注入的类型</h1>
<p>Guice有三种注入类型:</p>
<ul>
<li>
<p>field injection</p>
</li>
<li>
<p>constructor injection</p>
</li>
<li>
<p>method injection</p>
</li>
</ul>
<p>在上面的例子中,我们已经看到了属性注入的例子。为了看到构造器的注入,我们可以将Printing Service的代码修改如下:
    package com.insidecoding.guice;</p>
<pre><code>import javax.inject.Inject;

public class PrintingService implements IPrintingService {

    private ICachingService cs;

@Inject
public PrintingService(ICachingService cachingService) {
 this.cs = cachingService;
}

    @Override
    public void print(String s) {
        System.out.println(s);
        cs.cacheIt(s);
    }
}
</code></pre>

<p>注意,在使用属性注入的时候,Guice会调用无参构造函数来实例化对象。
方法注入可以用来注入方法的参数。这种Guice注入器在触发方法之前解析所有的依赖。被注入的方法可以拥有任意多的参数,并且方法名不会影响注入。方法注入示例代码如下:</p>
<pre><code> @Inject
   public void printMe(IPrintingService ps) {
      ps.print("Printing with Guice method injection");
   }
</code></pre>

<h1>ImplementedBy Vs bind()</h1>
<p>可以发现,上面的代码中使用了两种方法来达到接口与实现之间的绑定的:</p>
<ul>
<li>用<code>@ImplementedBy</code>来注解接口</li>
<li>在一个module中使用<code>bind()</code>方法来制定具体的实现:可以参照MyModule.configure()方法。</li>
</ul>
<p>对于一些简单的情况,例如一个接口对应一个实现,那么可以采用<code>@implementedBy</code>方式,如果你需要对绑定有更多的操作,或者说你需要定义多种实现,那么完全可以使用bind()方法。</p>
<p>一个值得注意的重要问题,Guice每次注入一个值得时候,默认地都会返回一个新的实例。你可以通过以下代码来切换到单利模式:</p>
<pre><code>bind(ICachingService).to(CachingService).in(Scopes.SINGLETON)
</code></pre>

<p>这个就属于Guice中比较高级的表现形式了,希望我开启了你对Guice的更大的渴求,后面你还会发现很多!如果你需要一个轻量级的DI框架,那么Guice已经玩爆Spring了。</p>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值