Guice BindingAnnotations泛型接口注入的问题

    今天被自己之前遗留的问题坑了一把,还是写篇日志记录一下吧。

    之前某个Jar里写了一个接口,然后该接口有几个不同的实现类,然后项目中使用了Guice来管理依赖并进行注入,因此对待这个情况就采用Guice的BindingAnnotations的方式来进行注入,但是在运行时Guice会抛出无法正确注入,找到实现类的错误提示,很是让人恼火。经过仔细观察Log发现问题就出在这个接口上。

    这个接口和Guice的例子唯一不同的地方就在于其是一个泛型接口,我们来举例说明这个问题:

public interface IFoo<T> {
    public  T foo();
}

    可以看到上面的泛型参数决定了foo函数的返回值,其实现类如下:

public static  class FooA implements IFoo<Integer> {

    @Override
    public Integer foo() {
        return 1;
    }
}

public static class FooB implements IFoo<String> {


    @Override
    public String foo() {
        return "hello";
    }
}

    然后在创建一个Module类来注册这些实现类:

    public static class FooModule extends AbstractModule {

        @Override
        protected void configure() {
            bind(IFoo.class).annotatedWith(Names.named("A")).to(FooA.class);
            bind(IFoo.class).annotatedWith(Names.named("B")).to(FooB.class);

        }
	}

    再写一个用来使用这些接口的测试类:

    @Singleton
    public static class TestFoo {
        @Named("A")
        @Inject
        private IFoo<Integer> fooA;

        @Named("B")
        @Inject()
        private IFoo<String> fooB;



        public void t() {
           Object a = fooA.foo();
           Object b = fooB.foo();
           System.out.println("A:" + a);
           System.out.println("B:" + b);
        }
    }    
    
    public static void main(String[] args) {
        Injector injector = Guice.createInjector(new FooModule());
        TestFoo f = injector.getInstance(TestFoo.class);
        f.t();

    }	

    当运行时我们会发现Guice会抛出如下运行时错误:

Exception in thread "main" com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for com.aceclarks.papaya.storage.test.TestGuiceNamedBind$IFoo<java.lang.Integer> annotated with @com.google.inject.name.Named(value=A) was bound.
  while locating com.aceclarks.papaya.storage.test.TestGuiceNamedBind$IFoo<java.lang.Integer> annotated with @com.google.inject.name.Named(value=A)
    for field at com.aceclarks.papaya.storage.test.TestGuiceNamedBind$TestFoo.fooA(TestGuiceNamedBind.java:57)
  while locating com.aceclarks.papaya.storage.test.TestGuiceNamedBind$TestFoo

2) No implementation for com.aceclarks.papaya.storage.test.TestGuiceNamedBind$IFoo<java.lang.String> annotated with @com.google.inject.name.Named(value=B) was bound.
  while locating com.aceclarks.papaya.storage.test.TestGuiceNamedBind$IFoo<java.lang.String> annotated with @com.google.inject.name.Named(value=B)
    for field at com.aceclarks.papaya.storage.test.TestGuiceNamedBind$TestFoo.fooB(TestGuiceNamedBind.java:57)
  while locating com.aceclarks.papaya.storage.test.TestGuiceNamedBind$TestFoo

2 errors
	at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:1004)
	at com.google.inject.internal.InjectorImpl.getProvider(InjectorImpl.java:961)
	at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1013)
	at com.aceclarks.papaya.storage.test.TestGuiceNamedBind.main(TestGuiceNamedBind.java:78)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

    其实这里发生的原因就是在于我们在FooModuleconfigure里注册的是绑定到接口IFoo的关联关系,但是Guice在运行时在TestFoo里的两个IFoo接口成员的声明是带有泛型参数的,Guice在注入时,没有找到对应的实现类,因此就会抛出如上的运行时异常,这个问题解决方法有两个:

  • 第一个方法是,在TestFoo的IFoo接口成员声明时,去掉泛型参数,这样Guice在运行时查找匹配的实现时就会按照IFoo的实现类去查找,而不是按照IFoo<Integer> 或 IFoo<String> 这样的带有泛型参数的接口去查找

  • 第二个方法是,在FooModule中configure函数里,在bind的时候使用TypeLiteral类来在注册的时候保持泛型参数信息进行注册,这样就可以保证注册的信息里是以带有泛型参数的接口注册的,代码例子如下:

      public static class FooModule extends AbstractModule {
    
          @Override
          protected void configure() {
              bind(new TypeLiteral<IFoo<Integer>>() {}).annotatedWith(Names.named("A")).to(FooA.class);
              bind(new TypeLiteral<IFoo<String>>() {}).annotatedWith(Names.named("B")).to(FooB.class);
    
          }
      }
    

转载于:https://my.oschina.net/pigsoldier/blog/223215

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值