Injeção de dependência com Guice #2: Anotações

guice

Fala galera!

Dando continuidade ao post Injeção de dependência com Guice #1: Introdução, hoje vou falar sobre as anotações da JSR e do Guice e como usa-las.

Anotações

@Inject

A @Inject com certeza é a anotação mais usada quando falamos de injeção de dependência com Guice. Ela é usada para informar ao Guice quando a classe depende da instância do um objeto qualquer e quer que o Guice se encarregue de “entregar” esta instância.

Existem 3 formas de declarar a pendência de uma classe usando o @Inject:

  • Atributo;
  • Método;
  • Construtor.
Exemplo de uso do @Inject em um atributo:
public class PagamentoService { 
   @Inject 
   private PagamentoDAO dao; 
}

googleQuando a classe PagamentoService for injetada através do injetor, automaticamente o Guice injetará uma instancia de PagamentoDAO, previamente configurado no modulo/binding.

Exemplo de uso do @Inject em um método:
public class PagamentoService { 
   private PagamentoDAO dao; 

   @Inject 
   public setPagamentoDao(PagamentoDAO pDao){
      dao = pDao;
   }
}

No exemplo a cima, estou solicitando ao Guice que ele injete PagamentoDAO no método set.

Exemplo de uso do @Inject em um construtor:
public class PagamentoService { 
   private PagamentoDAO dao; 

   @Inject
   public PagamentoService(PagamentoDAO pDao){
      dao = pDao;
   }
}

No exemplo a cima, estou solicitando ao Guice que ele injete PagamentoDAO no construtor do  PagamentoService.

Estas são as formas de usar o @Inject.

@Qualifier

Na maioria das vezes, criamos o binding ligando uma interface ao uma única implementação, normalmente usando a anotação @ImplementedBy. Em alguns casos existe várias implementações para uma determinada interface. Neste caso necessitamos identificar qual implementações queremos o Guice “entregue”, para isso usamos os qualifiers.

@Qualifier nada mais é que uma tag, rótulo, que indica ao Guice qual instância de implementação desejamos receber. No binding, “tagiamos” casa implementação com uma anotação do tipo @Qualifier, como pode ser visto abaixo:

public MyModule extends AbstractModule {
...
   /**
   * @return ICriticaRepository
   */
   @Provides
   @CriticaInDbRepository
   public ICriticaRepository provideCriticaInDbRepository() {
      return new CriticaRepositoryEmBancoImpl();
   }

   /**
   * @return ICriticaRepository
   */
   @Provides
   @CriticaInMemRepository
   public ICriticaRepository provideCriticaInMemRepository() {
      return new CriticaRepositoryEmMemoriaImpl();
   }
...
}

No exemplo a cima, criamos uma modulo contendo dois method providers. Nas linhas 7 e 16, podemos notar as anotações @CriticaInDbRepository@CriticaInMemRepository respectivamente. Estas anotações são qualifiers, ou seja, elas estão rotulando os providers, a fim de informar o Guice o que “entregar” quando for solicitado a instância de ICriticaRepository.

Mas isso não é tudo, na classe onde declaramos a dependência, através da anotação @Inject, precisamos também informar qual das implementações precisamos, desta forma:

...
   @Inject
   @CriticaInMemRepository
   private ICriticaRepository criticaRepository;
...

Pronto, assim o Guice saberá o que deve “entregar”, quando for solicitado.

Abaxio segue o código de uma das anotações qualificadoras:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface CriticaInMemRepository {
   // Interface que tipifica o repositorio de CriticaInMemRepository
}

@Named

A anotação @Named é muito parecida com a @Qualifier, inclusive serve para a mesma coisa, rotular as implementações.

No entanto não existe a necessidade de criar uma nova anotação, basta usa-la informando um identificador, desta forma:

 @Inject
 public RealBillingService(@Named("Checkout") CreditCardProcessor processor,
          TransactionLog transactionLog) {
    ...
 }

O binding configuramos assim:

bind(CreditCardProcessor.class) 
    .annotatedWith(Names.named("Checkout"))
    .to(CheckoutCreditCardProcessor.class);

@Provides

Quando o Guice não sabe como criar uma instância de sua implementação, seja pela quantidade de implementações de uma interface, ou pela complexabilidade de instância-la, nestes caso utilizamos a anotação @Provides.

Um exemplo do uso desta anotação no binding usando o qualifier. Podemos usar ela também na substituição de Factory por exemplo.

Veja mais em bindings

@Singleton

Por padrão, o Guice sempre retorna uma nova instância a cada solicitação de um mesmo tipo de objeto. No entanto, essa configuração pode ser alterada, possibilitando a definição de escopes.

A anotação @Singleton, serve para definir o escopo de aplicação ao configurar um binding, assim, o Guice “entregará” sempre a mesma instância quando for solicitada.

Vejamos exemplos de configuração:

// forma 1: No modulo, configurando o binding
bind(Service.class).to(ServiceImpl.class).in(Singleton.class);
// forma 2: No modulo, na criação de method provider
@Provides @Singleton
ClasseImpl getClasse(){return new ClasseA();}

//forma 3: Na definição da classe concreta, através da anotação
@Singleton
public class ClasseImpl (){..} 

Mais informações sofre definição de escopo, acesse o User Guide.

Fontes

um comentário

  1. […] a trás fiz dois posts fando sobe o Guice, Injeção de dependência com Guice #1: Introdução e Injeção de dependência com Guice #2: Anotações, o primeiro falando sobre o que é e seu objetivo, e o segundo como usar-lo em uma aplicação […]

    Curtir

Deixe um comentário