Google Guice依赖注入框架使用

Google Guice是一个轻量级依赖注入框架,和Spring类似。下面结合一些示例来讲解其使用方式。

首先引入maven依赖:

<dependency>
    <groupId>com.google.inject</groupId>
    <artifactId>guice</artifactId>
    <version>4.1.0</version>
</dependency>

示例1:

package com.jingchenyong.boundless.guice.example2;
 
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
 
@Singleton
class HelloPrinter {
    public void print() {
        System.out.println("Hello, World!");
    }
}
 
@Singleton
public class Sample {
 
    @Inject
    private HelloPrinter printer;
 
    public void hello() {
        printer.print();
    }
 
    public static void main(String[] args) {
        Injector injector = Guice.createInjector();
        Sample sample1 = injector.getInstance(Sample.class);
        sample1.hello();
    }
}

Guice最常用的两个注解就是@Singleton和@Inject,前者表示构建的对象是单例的,后者表示被标注的字段将使用Guice自动注入。示例1中使用Guice创建了一个注射器injector,Guice会自动装配依赖树,然后通过getInstance()方法获取指定的类实例并运行。

如果不使用Singleton标注类,那么每次获取实例时,Guice会重新构造一个,增加性能损耗。如下示例2所示,在Sample类上取消了Singleton注解,那么每次injector.getInstance(Sample.class)调用获取的都是不同的实例(对象堆地址不同)。

示例2:

package com.jingchenyong.boundless.guice.example2;
 
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
 
@Singleton
class HelloPrinter {
    public void print() {
        System.out.println("Hello, World!");
    }
}
 
public class Sample {
 
    @Inject
    private HelloPrinter printer;
 
    public void hello() {
        printer.print();
    }
 
    public static void main(String[] args) {
        Injector injector = Guice.createInjector();
        Sample sample1 = injector.getInstance(Sample.class);
        System.out.println(sample1);
        Sample sample2 = injector.getInstance(Sample.class);
        System.out.println(sample2);
    }
}
// 运行结果:
com.jingchenyong.boundless.guice.example2.Sample@74650e52
com.jingchenyong.boundless.guice.example2.Sample@15d0c81b

当一个接口有多个实现时,可以通过@ImplementedBy注解指定接口的具体实现类(不太优雅)。

示例3:

package com.jingchenyong.boundless.guice.example3;
 
import com.google.inject.Guice;
import com.google.inject.ImplementedBy;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
 
@ImplementedBy(ComplexHelloPrinter.class)
interface IHelloPrinter {
    void print();
}
 
@Singleton
class SimpleHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Simple World");
    }
}
 
@Singleton
class ComplexHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Complex World");
    }
 
}
 
@Singleton
public class Sample {
 
    @Inject
    private IHelloPrinter printer;
 
    public void hello() {
        printer.print();
    }
 
    public static void main(String[] args) {
        Injector injector = Guice.createInjector();
        Sample sample = injector.getInstance(Sample.class);
        sample.hello();
    }
}
 
// 运行结果
Hello, Complex World

为了解决在接口类上添加@ImplementedBy注解不优雅的方式,可以使用Guice Module定义装配规则,它相当于Spring的XML文件,只不过它的装配规则都是使用代码定义的。如下示例4所示:

示例4:

package com.jingchenyong.boundless.guice.example4;
 
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
 
interface IHelloPrinter {
    void print();
}
 
@Singleton
class SimpleHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Simple World");
    }
}
 
@Singleton
class ComplexHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Complex World");
    }
}
 
class SampleModule extends AbstractModule {
 
    @Override
    protected void configure() {
        bind(IHelloPrinter.class).to(SimpleHelloPrinter.class);
    }
 
}
 
public class Sample {
    @Inject
    private IHelloPrinter printer;
 
    public void hello() {
        printer.print();
    }
 
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new SampleModule());
        Sample sample = injector.getInstance(Sample.class);
        sample.hello();
    }
}

我们也可以使用@Named来指定依赖注入的实现(两种方式:字段注入和构造注入)

字段注入:

package com.jingchenyong.boundless.guice.example5;
 
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
 
interface IHelloPrinter {
    void print();
}
 
@Singleton
class SimpleHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Simple World");
    }
}
 
@Singleton
class ComplexHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Complex World");
    }
}
 
class SampleModule extends AbstractModule {
 
    @Override
    protected void configure() {
        bind(IHelloPrinter.class).annotatedWith(Names.named("simple")).to(SimpleHelloPrinter.class);
        bind(IHelloPrinter.class).annotatedWith(Names.named("complex")).to(ComplexHelloPrinter.class);
    }
 
}
 
public class Sample {
    @Inject
    @Named("simple")
    private IHelloPrinter simplePrinter;
    
    @Inject
    @Named("complex")
    private IHelloPrinter complexPrinter;
    
    public void hello() {
        simplePrinter.print();
        complexPrinter.print();
    }
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new SampleModule());
        Sample sample = injector.getInstance(Sample.class);
        sample.hello();
    }
}

构造注入:

package com.jingchenyong.boundless.guice.example5;
 
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
 
interface IHelloPrinter {
    void print();
}
 
@Singleton
class SimpleHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Simple World");
    }
}
 
@Singleton
class ComplexHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Complex World");
    }
}
 
class SampleModule extends AbstractModule {
 
    @Override
    protected void configure() {
        bind(IHelloPrinter.class).annotatedWith(Names.named("simple")).to(SimpleHelloPrinter.class);
        bind(IHelloPrinter.class).annotatedWith(Names.named("complex")).to(ComplexHelloPrinter.class);
    }
 
}
 
public class Sample {
    @Named("simple")
    private IHelloPrinter simplePrinter;
    
    @Named("complex")
    private IHelloPrinter complexPrinter;
    
    @Inject
    public Sample(@Named("simple") IHelloPrinter simplePrinter, @Named("complex") IHelloPrinter complexPrinter) {
        this.simplePrinter = simplePrinter;
        this.complexPrinter = complexPrinter;
    }
    
    public void hello() {
        simplePrinter.print();
        complexPrinter.print();
    }
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new SampleModule());
        Sample sample = injector.getInstance(Sample.class);
        sample.hello();
    }
}

有时候需要直接注入一个对象实例,而不是从依赖关系中解析。如果我们注入基本类型可以在SampleModule的configure()方法中添加如下语句:

bind(String.class).annotatedWith(Names.named("url")).toInstance("http://www.baidu.com");

那么在Sample中就可以添加如下语句进行自动装配:

@Named("url")
private String url;

当一个对象很复杂,无法使用简单的构造器来生成的时候,我们就可以使用使用实现Provider接口的类来生成复杂对象,然后在SampleModule的configure()方法中配置该复杂对象

(1)使用实现Provider接口的类来生成复杂对象

class LogParam {
    @Override
    public String toString() {
        return "我是test";
    }
}
// Log类为Sample类需要加载的复杂对象的抽象类(说它复杂因为包含了LogParam的实例)
abstract class Log {
    protected LogParam test;
 
    public abstract void setTest(LogParam test);
 
    public abstract LogParam getTest();
}
 
// Log的实现类
class MyLog extends Log {
 
    @Override
    public void setTest(LogParam test) {
        this.test = test;
    }
 
    @Override
    public LogParam getTest() {
        return this.test;
    }
 
}
 
class LogProvider implements Provider<Log> {
 
    private final LogParam test;
    // 这里会自动装配LogParam实例,也可在get方法中自定义构造该实例
    @Inject
    public LogProvider(LogParam test) {
        this.test = test;
    }
 
    @Override
    public Log get() {
        MyLog myLog = new MyLog();
        myLog.setTest(test);
        return myLog;
    }
 
}

(2)在SampleModule的configure()方法中配置该复杂对象

bind(Log.class).toProvider(LogProvider.class);

(3)Sample类中装配使用Log实现类

@Named("simple")
private IHelloPrinter simplePrinter;
    
@Named("complex")
private IHelloPrinter complexPrinter;
    
private Log log;
    
@Inject
public Sample(@Named("simple") IHelloPrinter simplePrinter, @Named("complex") IHelloPrinter complexPrinter, Log log) {
    this.simplePrinter = simplePrinter;
    this.complexPrinter = complexPrinter;
    this.log = log;
}

Guice还可以自动注入Set,Map容器,添加扩展库依赖

<dependency>
    <groupId>com.google.inject.extensions</groupId>
    <artifactId>guice-multibindings</artifactId>
    <version>4.1.0</version>
</dependency>

注入Set

package com.jingchenyong.boundless.guice.example6;
 
import java.util.Set;
 
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.multibindings.Multibinder;
 
interface IHelloPrinter {
    void print();
}
 
@Singleton
class SimpleHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Simple World");
    }
}
 
@Singleton
class ComplexHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Complex World");
    }
}
 
class SampleModule extends AbstractModule {
 
    @Override
    protected void configure() {
        Multibinder<IHelloPrinter> printers = Multibinder.newSetBinder(binder(), IHelloPrinter.class);
        printers.addBinding().to(SimpleHelloPrinter.class);
        printers.addBinding().to(ComplexHelloPrinter.class);
    }
 
}
 
public class Sample {
 
    @Inject
    private Set<IHelloPrinter> printers;
 
    public void hello() {
        for (IHelloPrinter printer : printers) {
            printer.print();
        }
    }
 
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new SampleModule());
        Sample sample = injector.getInstance(Sample.class);
        sample.hello();
    }
}
// 运行结果
Hello, Simple World
Hello, Complex World

注入Map

package com.jingchenyong.boundless.guice.example6;
 
import java.util.Map;
 
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.multibindings.MapBinder;
 
interface IHelloPrinter {
    void print();
}
 
@Singleton
class SimpleHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Simple World");
    }
}
 
@Singleton
class ComplexHelloPrinter implements IHelloPrinter {
 
    @Override
    public void print() {
        System.out.println("Hello, Complex World");
    }
}
 
class SampleModule extends AbstractModule {
 
    @Override
    protected void configure() {
        MapBinder<String, IHelloPrinter> printers = MapBinder.newMapBinder(binder(), String.class, IHelloPrinter.class);
        printers.addBinding("simple").to(SimpleHelloPrinter.class);
        printers.addBinding("complex").to(ComplexHelloPrinter.class);
    }
 
}
 
public class Sample {
 
    @Inject
    private Map<String, IHelloPrinter> printers;
 
    public void hello() {
        for (String name : printers.keySet()) {
            printers.get(name).print();
        }
    }
 
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new SampleModule());
        Sample sample = injector.getInstance(Sample.class);
        sample.hello();
    }
}
//运行结果
Hello, Simple World
Hello, Complex World

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值