user2498079
user2498079

Reputation: 3012

When & Why use annotation binding?

I'm trying to understand the use case of Binding Annotation and why to use them. I've found some examples online like the following that show how to use annotation binding but I'm failing to understand why annotation binding is needed in the first place? And why would we want to provide multiple objects of the same type?

Occasionally, you may want multiple bound instances of the same type. For instance you may want both a FooHttpClient <: HttpClient and a BarHttpClient <: HttpClient.

package example.http.clients.annotations;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.Qualifier;

import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Qualifier
@Target({ FIELD, PARAMETER, METHOD })
@Retention(RUNTIME)
public @interface FooClient {}

object MyHttpClientsModule extends TwitterModule {
  val fooClientDestination = flag("foo.client.dest", "Foo Client Destination")
  val barClientDestination = flag("bar.client.dest", "Bar Client Destination")

  @Singleton
  @Provides
  @FooClient
  def providesFooHttpClient: HttpClient = {
    val dest = fooClientDestination.get match {
      case Some(value) => value
      case _ => "DEFAULT"
    }

    new HttpClient(dest)
  }

  @Singleton
  @Provides
  @BarClient
  def providesBarHttpClient: HttpClient = {
    val dest = barClientDestination.get match {
      case Some(value) => value
      case _ => "DEFAULT"
    }
    new HttpClient(dest)
  }
}

Questions:

  1. Why would we want to differentiate between multiple instances of the same type?
  2. If 2 classes implement a similar interface but have different implementations, why would we not provide the 2 different implementations as 2 separate objects since they both do the job differently?

EDIT: If the underlying implementation is different then wouldn't it be easier to just provide 2 separate objects of different types even though those 2 objects implement the same interface?

interace A {
  //only one method 
  void foo()
}

class X implements A {

   @override void foo() {
     
   //different implementation then Class Y
   }
}

class Y implements A {

   @override void foo() {
     
   //different implementation then Class X
   }
}

why not provide object X and Y rather then providing objects of type A and then use @Name/Binding annotation?

Upvotes: 1

Views: 169

Answers (1)

Louis Wasserman
Louis Wasserman

Reputation: 198471

  1. Do you think your application will only need one String? Or one Set<String>? Or boolean, for whether or not varying flags are set?
  2. Generally, the use case is for swapping in different implementations, especially for tests. For example, in a test you might want to use a simple local Set when in production code you'd actually be sending RPCs to a whole database.

Upvotes: 1

Related Questions