【你好Eureka】一:轻量级DI框架Guice入门

每日一句

办天下大事,贵实心,尤贵虚心。非真知灼见不能办事,亦不能论事,贵耳贱目,最足误事。

前言

你可能会问 :既然是eureka专栏 为什么要说Guice?Guice又是什么?
Eureka专栏为什么说Guice 这个很简单 因为Eureka依赖了Guice,而Guice又是一个很精美的依赖注入框架。是值得我们学习的。
Guice是什么?上面说了是专注于DI的框架,小巧精美。国内很多框架都依赖了它。毕竟是google出品的 那就肯定是精品。好了 废话不多说了 大家对依赖注入再了解不过了 再者毕竟我们的主角不是它。直接上demo把。

获取对象

@Test
  public void test1(){
    Injector injector = Guice.createInjector(new MyModule());
    Animal dog1 = injector.getInstance(Dog.class);
    Animal dog2 = injector.getInstance(Dog.class);
    System.out.println(dog1 == dog2);
  }
  public static interface Animal{}

  public static class Dog implements Animal{
  }
  public static class MyModule extends AbstractModule{
    @Override
    protected void configure() {
    }
  }

上面的示例 创建了一个Animal接口 一个Dog实现类。
MyModule可以简单理解为Spring的配置类。
Injector injector = Guice.createInjector(new MyModule()); 简单理解创建一个实例工厂 我们可以从这个工厂中获取我们想要的实例。
我们上面获取的dog1和dog2不是一实例。说明默认情况下 Guice不是以单利返回的。
如果想获取单例的实例怎么办?很简单 在Dog类上加上 @Singleton注解。注意、注意 这里有两个@Singleton注解 一个是javax.inject包下面的 一个是guice原生的导哪个包,这里其实任何一个都可以。至于为什么 你可以自己品!

AbstractModule

还是在上个例子的基础上构建

//新增了一个Cat实现类
  public static class Cat implements Animal{}
 @Test
  public  void test2(){
    Injector injector = Guice.createInjector(new MyModule());
    Animal animal1 = injector.getInstance(Animal.class);
    Animal animal2 = injector.getInstance(Animal.class);
    System.out.println(animal1 == animal2);
  }
  public static class MyModule extends AbstractModule{
    @Override
    protected void configure() {
    }
    @Provides
    @Singleton
    public Animal providerCat(){
      return new Cat();
    }
  }

@Provides注解相当于把providerCat方法包装成Provider对象 然后放到容器内 类似Spring中的@Bean注解

public static class MyModule extends AbstractModule{
    @Override
    protected void configure() {
    bind(Animal.class).toProvider((Provider<Cat>) () -> new Cat()).in(Scopes.SINGLETON);
    }
 }   

使用bind方法来绑定一个Provider 效果和上面是一样的。但是更建议这种写法。
当然你还有可以用@ProviderBy注解来直接指定当前的提供者,但是你知道就行不要真的这么干。

也可以使用bind(xxx.class).to()直接绑定

上面的列子我们也可以改为

 @Override
    protected void configure() {
    bind(Animal.class).to(Cat.class).in(Scopes.SINGLETON);
    }
 }   

@Inject 注解注入实例

public class Demo1 {
  private final String message;
  private final int count;
  @Inject
  public Demo1( String message , int count){
    this.message = message;
    this.count = count;
  }
  void sayHello(){
    for (int i=0; i < count; i++) {
      System.out.println(message);
    }
  }
  public static void main(String[] args) {
    Injector injector = Guice.createInjector(new MyModule());
    Demo1 instance = injector.getInstance(Demo1.class);
    instance.sayHello();
  }
  public static class MyModule extends AbstractModule{
    @Override
    protected void configure() {
    }
    @Provides
    static Integer provideCount(){
      return 3;
    }
    @Provides
    static String provideMessage(){
      return "hello word";
    }
  }
}

上面定义了一个AbstractModule 在里面定义了两个方法 使用 @Provides 注册到容器。
然后再Demo1中的构造方法使用 @Inject来进行注入。 运行例子发现能成功的获取到值。
注入的方式很简单 只需要使用注解**@Inject**。

绑定注解

通过上面的例子细心的朋友会有问题:如果我们需要Animal接口下面有 Cat和Dog但是我们都需要使用怎么办?

  @Qualifier
  @Target({ FIELD, PARAMETER, METHOD })
  @Retention(RUNTIME)
  public static @interface BirdAnno {
  }
  @Qualifier
  @Target({ FIELD, PARAMETER, METHOD })
  @Retention(RUNTIME)
  public static @interface QwlAnno {
  }
  public static class MyModule extends AbstractModule{
    @Override
    protected void configure() {
      //使用annotatedWith来绑定注解
      bind(Animal.class).annotatedWith(BirdAnno.class).to(Bird.class);
      bind(Animal.class).annotatedWith(QwlAnno.class).to(Qwl.class);
    }
  }
  public static class Zoo{
     //在注入的时候 加入绑定的注解即可
    @Inject
    public Zoo(@BirdAnno Animal bird , @QwlAnno Animal qwl){
      System.out.println(bird);
      System.out.println(qwl);
    }
  }

随便定义了两个注解BirdAnno和QwlAnno 唯一注意的一点就是 需要加**@Qualifier来修饰 当然你也可以加@BindingAnnotation来替换@Qualifier**,当然强烈不建议你这么做。你要问我为什么,@Qualifier是 JSR-330 中的注解 也就是java的嫡系。而**@BindingAnnotation是guice自带的注解。这也就是上面说的两个@Singleton**为什么都可以,但是你用哪一个呢?其实是一样的道理。

实例绑定

 bind(String.class).annotatedWith(Names.named("JdbcUrl")).toInstance("jdbc:mysql://localhost/test");
 bindConstant().annotatedWith(HttpPort.class).to(8080);
###使用
@Inject
@HttpPort
private Integer httpPort;

bindConstant:可以用来绑定字面量类型的实例。当然你也可以使用**bind().annotatedWith().toInstance()**来替代。

总结

上面的内容 足以满足Eureka的需求了。其他的我就不赘述了 ,用法都还是比较容易上手的。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值