Guice 4.1教程

Posted stevenczp

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Guice 4.1教程相关的知识,希望对你有一定的参考价值。

Guice是Google开发的一个开源轻量级的依赖注入框架,运行速度快,使用简单。

 

项目地址:https://github.com/google/guice/

最新的版本是4.1,本文基于此版本。

 

 

0. 什么是依赖注入?

依赖注入(Dependency Injection)是一种思想。

在一般的编程中,如果我们想要使用一个class的实例,那么必须要调用构造方法new class()手动将其实例化,如果这个class中又有对其他class属性的引用,那么在构造方法中,又要调用其他class的构造方法将其实例化。

这就是“依赖”。

Guice这种依赖注入框架的作用就是接管class之间的依赖关系,如果我们想要使用一个class的实例,Guice会自动生成实现类的实例并交给我们。

这个过程就叫做“注入”。

 

1. 利用Module的依赖注入

//定义Dog接口
public interface Dog {
    void bark();
}

//定义BlackDog实现类
public class BlackDog implements Dog{
    @Override
    public void bark() {
        System.out.println("i am black dog");
    }
}

//依赖注入
public class GuiceTest {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new Module() {
            @Override
            public void configure(Binder binder) {
                binder.bind(Dog.class).to(BlackDog.class);
            }
        });
        Dog dog = injector.getInstance(Dog.class);
        dog.bark();
    }
}

输出结果如下

i am black dog

这个例子非常简单,先在自定义的Module中将Dog接口与BlackDog实现类关联起来。此时如果调用getInstance方法想要获取Dog接口的实例,就自动创建一个BlackDog的实例并返回。

 

2. 绑定到实例的依赖注入

public static void main(String[] args) {
        Injector injector = Guice.createInjector(new Module() {
            @Override
            public void configure(Binder binder) {
                binder.bind(Dog.class).toInstance(new BlackDog());
            }
        });

        Dog dog = injector.getInstance(Dog.class);
        dog.bark();
    }

可以看到Dog接口已经与某个BlackDog的实例绑定起来了。

 

3. 利用Provider的依赖注入

    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new Module() {
            @Override
            public void configure(Binder binder) {
                binder.bind(Dog.class).toProvider(new Provider<Dog>() {
                    Dog dog = new BlackDog();

                    @Override
                    public Dog get() {
                        return dog;
                    }
                });
            }
        });

        Dog dog = injector.getInstance(Dog.class);
        dog.bark();
    }

换了一种方法的绑定,在自定义的Provider类中,我们可以执行一些复杂的操作。

 

4. 基于注解的依赖注入

可以在接口上添加@ImplementedBy完成绑定操作

@ImplementedBy(BlackDog.class)
public interface Dog {
    void bark();
}

public class BlackDog implements Dog{
    @Override
    public void bark() {
        System.out.println("i am black dog");
    }
}

public class GuiceTest {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector();
        Dog dog = injector.getInstance(Dog.class);
        dog.bark();
    }
}

可以看到没有为Guice指定任何Module,也完成了依赖注入的操作

当然,也可以用@ProvidedBy注解完成绑定操作

@ProvidedBy(BlackDogProvider.class)
public interface Dog {
    void bark();
}

public class BlackDogProvider implements Provider<Dog> {
    @Override
    public Dog get() {
        return new BlackDog();
    }
}

public class GuiceTest {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector();
        Dog dog = injector.getInstance(Dog.class);
        dog.bark();
    }
}

基于注解的依赖注入其实与基于Module的依赖注入差别不大,只是口味上的区别

但是Module里的配置会覆盖注解里的配置

 

5. 单例

在默认情况下,每次调用getInstance方法,都会创建一个新的对象并返回(Provider注入与实例注入除外)

@ImplementedBy(BlackDog.class)
public interface Dog {
    void bark();
}

public class BlackDog implements Dog{
    @Override
    public void bark() {
        System.out.println("i am black dog");
    }
}

public class GuiceTest {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector();
        for (int i = 0; i < 10; i++) {
            System.out.println(injector.getInstance(Dog.class).hashCode());
        }
    }
}

调用10次getInstance方法,分别计算得到对象的hashCode,结果如下

1709366259
1335298403
1643691748
2068434592
143110009
2142003995
1535634836
1846412426
1539805781
1206883981

可以看出,每次调用getInstance方法,都会生成一个全新的对象。

如果我们希望返回的是同一个对象(单例模式),那么只需要在实现类上加一个@Singleton注解

@ImplementedBy(BlackDog.class)
public interface Dog {
    void bark();
}

@Singleton
public class BlackDog implements Dog{
    @Override
    public void bark() {
        System.out.println("i am black dog");
    }
}

public class GuiceTest {
    public static void main(String[] args) {
        Injector injector = Guice.createInjector();
        for (int i = 0; i < 10; i++) {
            System.out.println(injector.getInstance(Dog.class).hashCode());
        }
    }
}

运行结果如下:

1632492873
1632492873
1632492873
1632492873
1632492873
1632492873
1632492873
1632492873
1632492873
1632492873

可以看到@Singleton注解已经生效,调用getInstance方法返回的对象已经是单例的了

 

6. 单接口多实现类

 

以上是关于Guice 4.1教程的主要内容,如果未能解决你的问题,请参考以下文章

Guice vs AspectJ

不使用支持库的 Android 4.0、4.1 (<4.2) 中嵌套片段的最佳实践

玩 2.5 剪影 4 - 带有 guice 的 DI

Google Guice、Google Gin 和 Spring

web代码片段

VIM 代码片段插件 ultisnips 使用教程