Injeção de Dependência Dinâmica

4 respostas
giovannicandido

Alguém sabe como fazer fazer injeção de dependência passando em tempo de execução o tipo de dependência? Eu quero transformar uma factory method em um bean injetável.

Uma factory method como essa:

public class Fabrica {
 public IObjeto getObjeto(String modelo){
 if(modelo == "a"){
   return new ObjetoA;
else if(modelo == "b"){
   return new ObjetoB;
 }
}

Queria usar CDI de forma semelhante à

@Named
public class Fabrica {

public IObjeto getObjeto(String smodelo){
  @Inject
  @ObjetoQualifier(modelo = smodelo)
  IObjeto objeto;
  return objeto;
}

Mas isso não funciona pois “smodelo” tem que ser uma constante. O problema é que a interface IObjeto tem várias implementações possíveis, uma para cada modelo, e o número de modelos não é conhecido a priori, mas o cliente da fábrica é que sabe o modelo que está cadastrado em uma base, ele cria Objetos do tipo IObjeto para executar operações conforme o modelo.
Caso não exista implementadores daquela interface para o modelo especificado deve ser retornado null, para que o cliente gere uma exceção.
Pode ser que esteja tentando usar Injeção de Dependência de forma incorreta, não sendo possível usar dessa maneira vou ter que usar a fabrica, mas para cada Implementação de IObjeto terei que modificar a fábrica para retorná-lo, vou pesquisar sobre OSGI para ver se resolve.

Alguma idéia?

4 Respostas

giovannicandido

Achei uma forma de fazer aqui: http://stackoverflow.com/questions/6621403/replace-factory-based-object-creation-with-cdi-mechanism

No meu caso ficou assim:

import javax.enterprise.inject.Instance;
public class Fabrica {
 @Inject
 Instance<IObjeto> instanciasObjeto;
 public IObjeto getObjeto(String modelo){
  for(IObjeto objeto:instanciasObjeto){
   if(objeto.podeExecutar(modelo)){
     return objeto;
    }
  }
    return null;

}

Tive que alterar a interface IObjeto para que todos que a implementem digam se podem executar para aquele modelo

giovannicandido

Seria interessante se alguém mais tiver uma solução diferente. O problema com a solução acima é que apenas uma implementação será executada, bem no meu caso não é problema e sim requisito, outra desvantagem é ter que alterar a interface IObjeto

Estava pensando em um forma de fazer usando eventos, assim os implementadores apenas subscrevem em um evento que dispara quando devem ser executados e passa como parametro o modelo, assim cada implementador verifica se executa ou não dado o modelo. Desse modo múltiplos implementadores podem executar (se esse for o requisito)

ViniGodoy

E por que não usa reflexão?

C

Para ter como vantagem a injeção do CDI e a flexibilidade de um ponto de injeção não tão acoplado, eu nunca tentei, mas acredito que uma solução seria algo como citado neste link : http://docs.jboss.org/weld/reference/1.1.5.Final/pt-BR/html/injection.html na sessão 4.10. Obtendo uma instância contextual através de pesquisa programática.

Assim voce poderia anotar dinamicamente a classe.

Criado 19 de junho de 2012
Ultima resposta 20 de jun. de 2012
Respostas 4
Participantes 3