• Guice 依赖绑定


    Guice 依赖绑定

    连接绑定(Linked Bingdings)

    连接绑定是 Guice 最基本的一种绑定方式。这种绑定方式我们需要在自己定义的 Moduleconfigure() 中编写绑定。如下所示:

    public class BillingModule extends AbstractModule {
      @Override
      protected void configure() {
        bind(Animal.class).to(Cat.class);
      }
    }
    

    现在当调用 injector.getInstance(Animal.class) 时,就会返回一个 Cat 对象。

    连接绑定也可以组成链式,如下:

    public class BillingModule extends AbstractModule {
      @Override
      protected void configure() {
        bind(Animal.class).to(Cat.class);
        bind(Cat.class).to(PersianCat.class);
      }
    }
    

    此时

    注解绑定(Binding Annotations)

    某些时候我们的一个接口可能有很多的实现,而此时我们在代码的某个地方想让这个接口绑定其中的某体格实现,这个时候直接使用连接绑定就不行了。

    此时我们可以使用注解(Annotation)来绑定,我们可以使用自己定义的注解,举例:

    @BindingAnnotation
    @Target({ FIELD, PARAMETER, METHOD })
    @Retention(RUNTIME)
    public @interface Persian {}
    

    这个注解中需要主要的是 @BindingAnnotation 这个地方,这是由 Guice 提供的,来标识这个注解就是用来标识绑定的,我们也可以称其为绑定注解(Binging Annotation)。当一个对象被多个绑定注解所标识时,Guice 就会报错

    @Inject
    @Persian
    private Cat cat;
    

    我们仍然需要指定绑定关系,如下:

    bind(Cat.class)
    	.annotatedWith(Persian.class)
        .to(PersianCat.class);
    

    其实,如果没有什么特殊需求的话,Guice 已经为我们提供了一种默认的注解来辅助我们进行对象绑定,@Named。仍然以上述例子来说明:

    @Inject
    @Named("persian")
    private Cat cat;
    

    此时绑定关系可以这样写:

    bind(Cat.class)
    	.annotatedWith(Names.named("persian"))
        .to(PersianCat.class);
    

    实例绑定(Instance Bindings)

    顾名思义,直接使用实例而来进行绑定。通常这种绑定作用于没有什么依赖和实现的对象上。

    最普遍的应用大概就是一些参数变量的绑定了,直接 Copy 官方文档的代码:

    bind(String.class)
    	.annotatedWith(Names.named("JDBC URL"))
    	.toInstance("jdbc:mysql://localhost/pizza");
    bind(Integer.class)
    	.annotatedWith(Names.named("login timeout seconds"))
    	.toInstance(10);
    

    如果实例过于复杂,就不要使用这样的方式绑定,因为这些代码写在 Moduleconfigure() 中,会拖慢程序的启动。稍后会说到,可以使用 @Provides 来代替。

    @Provides 方法

    当需要某种类型的对象时,就可以使用 @Provides 方法。这类方法必须定义在 Module 中,且用 @Provides 标识,如下:

    public class AppModule extends AbstractModule {
        protected void configure() {}
    
        @Provides
        PersianCat providePersianCat() {
            PersianCat persianCat = new PersianCat();
            persianCat.setName("Foo");
            return persianCat;
        }
    }
    

    这时当注入 PersianCat 类型对象时,就会从 providePersianCat() 方法中生成。

    @Provides 方法也可以添加注解,这里就直接贴官方代码了,不做赘述:

    @Provides @PayPal
    CreditCardProcessor providePayPalCreditCardProcessor(@Named("PayPal API key") String apiKey) {
    	PayPalCreditCardProcessor processor = new PayPalCreditCardProcessor();
    	processor.setApiKey(apiKey);
    	return processor;
    }
    

    Provider 绑定(Provider Bindings)

    当使用了太多 @Provides 方法绑定之后,Module 就会显得臃肿不堪。这时可以试着将这些方法从 Module 中剥离出来,只要实现 Guice 提供的 Provider 的接口即可。

    public interface Provider<T> {
    	T get();
    }
    

    Provider 接口只有一个 get() 方法,其实很简单。直接把上述代码移至此处。

    public class PersianCatProvider implements Provider<PersianCat> {
    
        public PersianCat get() {
            PersianCat persianCat = new PersianCat();
            persianCat.setName("Foo");
            return persianCat;
        }
    }
    

    最后如果需要,可以指定类型绑定到 Provider:

    bind(Cat.class).toProvider(PersianCatProvider.class);
    

    构造方法绑定(Constructor Bindings)

    有时候当绑定对象有多个构造方法时,我们可能需要指定某一个构造方法,这时可以使用构造方法绑定来达到目的。如下:

    try {
    	bind(PersianCat.class).toConstructor(PersianCat.class.getConstructor(String.class));
    } catch (NoSuchMethodException e) {
    	e.printStackTrace();
    }
    

    需要注意的是,这种绑定方式需要捕获异常。

    @ImplementedBy 与 @ProvidedBy

    @ImplementedBy 注解用于简化绑定配置,通常用于指定默认的实现类型。最常用的场景在于编写 Dao 或者 Service 时,指定 Interface 的实现类。直接给出官方示例:

    @ImplementedBy(PayPalCreditCardProcessor.class)
    public interface CreditCardProcessor {
    	ChargeResult charge(String amount, CreditCard creditCard) throws UnreachableException;
    }
    

    等价于:

    bind(CreditCardProcessor.class).to(PayPalCreditCardProcessor.class);
    

    @ProvidedBy 也是顾名思义:

    @ProvidedBy(DatabaseTransactionLogProvider.class)
    public interface TransactionLog {
    	void logConnectException(UnreachableException e);
    	void logChargeResult(ChargeResult result);
    }
    

    等价于

    bind(TransactionLog.class).toProvider(DatabaseTransactionLogProvider.class);
    
  • 相关阅读:
    JDBC第一部分
    java mysql学习第三部分
    java mysql 第六部分
    java mysql学习第五部分
    java mysql学习第二部分
    java mysql学习第一部分
    元注解
    改良之前写的模拟栈代码
    java中如何自定义异常
    java中的语法规则
  • 原文地址:https://www.cnblogs.com/snowInPluto/p/5993097.html
Copyright © 2020-2023  润新知