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?
Achei uma forma de fazer aqui: http://stackoverflow.com/questions/6621403/replace-factory-based-object-creation-with-cdi-mechanism
No meu caso ficou assim:
[code]
import javax.enterprise.inject.Instance;
public class Fabrica {
@Inject
Instance instanciasObjeto;
public IObjeto getObjeto(String modelo){
for(IObjeto objeto:instanciasObjeto){
if(objeto.podeExecutar(modelo)){
return objeto;
}
}
return null;
}[/code]
Tive que alterar a interface IObjeto para que todos que a implementem digam se podem executar para aquele modelo
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)
E por que não usa reflexão?
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.