Injeção de Dependências x Lookups

10 respostas
rruppel

ae galera,

estou ainda sedimentando conhecimentos em relação a Dependency Injections, então estava pensando em tudo que já li e fiquei com uma dúvida e venho pedir vossa ajuda

eu li que a injeção de dependencias serve, inclusive, para substituir os lookups (que aparentemente não são tão recomendados). Porém, eu uso os lookups em classes minhas q não são beans

(agora me venho uma dúvida básica: eu tinha como verdade até agora que para estar dentro do container, bastava ser bean. E sendo bean, já estava automaticamente dentro do container).

Bom… considerando que a minha hipótese em parenteses esteja certa, o jeito de evitar os lookups seria transformando todas as classes nas quais eu usava lookups em beans e injetando as dependencias nesses beans… tá certo isso?

abraços

10 Respostas

sergiotaborda

O seu codigo é mais ou menos assim

class AlgumaClasse {

   void algumMetodo (){

         OutraClasse outra = Lookup.lookup(OutraClasse.class);
         outra.executaMetodoqualquer();
   }

}

// em outro lugar

AlgumaClasse alguma = new AlgumaClasse ();
alguma.algumMetodo();

O que a injeção faz é isto:

  1. encapsula a inicialização de AlgumaClasse (aliás, de todas as classes)
AlgumaClasse alguma = InjectionContainer.newInstance(AlgumaClasse.class);
alguma.algumMetodo();
  1. Faz o lookup por vc e envia (injeta) para o objeto interessado o objeto encontrado
    A injeção pode ser feita de tres formas: via construtor, via setter ou via alteração direta de um atributo
    com reflection. Com setter seria assim:
class AlgumaClasse {

   OutraClasse outra;
   public void setOutraClasse (OutraClasse outra){
             this.outra = outra;
   }

   void algumMetodo (){

         outra.executaMetodoqualquer();
   }

}

Só isso.

Como o container de injeção sabe qual classe e com que parametros iniciar o objecto da classe OutraClasse?
Simples, ele faz assim

OutraClasse outra= InjectionContainer.newInstance(OutraClasse.class);
algumaClass.setOutraClasse(outra);

Isso é um processo recursivo, que no fim, seta todas as dependencias.
Como o container é tb uma fabrica a instanciação pode ser parameterizada.
Básicamente é isso.

rruppel

opa… valeu pela resposta!.. muito boa! mas acho q isso eu já tinha entendido… (e me parece q tem até um errinho na sua resposta pq vc colocou o mesmo código em dois lugares diferentes)…

mas sem querer parecer ingrato, a minha dúvida era um pouco diferente… deixa eu ver se consigo estruturá-la melhor:

1º -> Usar lookups é uma prática não recomendada? (pq parece q eu estou lendo isso nos lugares q andei olhando… meio redundante mas tudo bem)

2º -> Em caso afirmativo, qual o jeito de substituir os lookups? Com Injeção de Dependencias?

3º -> Em caso afirmativo, vêm uma pergunta final: para usar injeção de dependencias então eu devo fazer de TODAS as classes nas quais eu usava lookups beans? ou seja, mudar as classes q usavam lookups para q elas sejam beans e q portanto estejam dentro do container e q portanto possam receber injeções? Ou existem outras formas de fazer isso?

agradeço novamente a resposta já dada e muito obrigado pelos esclarecimentos… quem sabe no futuro não sou eu q estarei respondendo aki ? :smiley:

saoj

Teu código vai ficar atrelado ao lookup. Melhor deixar que o container INJETE como meu xará falou!

Usando um container de IOC que faz a injeção pra vc.

Tem que fazer isso mesmo. Na verdade IoC preza pelo uso de interfaces e não implementações. Sua classe está atrelada a interfaces e é o container que decide qual implementação usar. DECIDE = vc configura por fora.

Veja se isso aqui te ajuda: http://forum.mentaframework.org/posts/list/477.page

rruppel

opa… muito obrigado pela resposta!

eu entendi tudo direitinho então… a única coisa q eu não gosto é o seguinte:

ótimo! tirei todas as dependências do meu projeto… mas agora eu dependo de um container de IoC… não é um pouco ruim isso?

talvez a resposta seja: não é ruim… a idéia é q esses containers serão desenvolvidos por gente muito capacitada e eles cuidarão de vários problemas q vc não vai precisar se preocupar… entre eles destaca-se a concorrência…

mesmo assim eu ainda não me sinto muito convencido… claro q para o estado atual no qual o meu projeto já tem classes dependentes de um container… então não há problemas colocar as outras classes dentro do container…

e talvez possamos pensar q a minha classe não está dependendo de um container… afinal eu poderia fazer o container com um código meu mesmo… como o sérgio começou a explicar…

enfim… se alguém perceber q estou eskecendo de algo nesses meus pensamentos eu agradeceria o esclarecimento… mas acho q estou com as idéias corretas :smiley:

saoj

O que vc chama de depender? Estar atrelado? Depender dele para o funcionamento? Eu prefiro IoC não intrusivo, ou seja, suas classes ficam totalmente independentes do container do ponto de vista do acoplamento, como o link que eu coloquei lá mostra…

IoC tem pouco a ver com concorrencia. Qual é o seu contexto? Aplicação web? Aplicação distribuída? Desktop?

Pelo menos numa aplicação web, vc tem os escopos APPLICATION (singleton), SESSION, e REQUEST. Não entendi o que vc quiz dizer com concorrencia e IoC.

sergiotaborda

rruppel:
opa… valeu pela resposta!.. muito boa! mas acho q isso eu já tinha entendido… (e me parece q tem até um errinho na sua resposta pq vc colocou o mesmo código em dois lugares diferentes)…

qual seria esse codigo ?

entenda que o container de injeção continuará fazendo lookups e que o seu codigo continuará fazendo lookups pois em vez de escrever o codigo

OutraClasse outra = Lookup.lookup(OutraClasse.class);

vc escreverá

OutraClasse outra = InjectionContainer.newInstance(OutraClasse.class);

Que no fim é a mesma coisa. A diferença é que usando o container vc tem injeção configurável.
É a configuração que é o ganho aqui e não a eliminação do lookup.

Quando se diz que IoC é preferivel a lookup esta-se pensando que para cada classe existe um lookup dela.
(como era comum em EJB pre-3)

Todas as classes já deveriam ser beans :wink:
Aqui fiquei com duvida se está falando de EJB Beans ou de POJO beans.
Para jogo um framework de injeção pode ser uma boa. Para EJB também, mas ai é preciso ter em atenção que EJB é um padrão e usar qq coisa fora do padrão é um tiro no pé ( ai mais vale não usar EJB)

saoj

Acho que vc se enganou aqui. Um container de IoC deve usar Injection por reflection, ou seja, a classe que está recebendo nem vai saber que o container existe. Vai apenas receber a implementação do componente (interface) que precisa.

Como o container vai saber que tem que injetar uma coisa ali?

Dois approaches:

  1. ID do componente == nome da propriedade (é o que eu prefiro porque não é intrusivo = IoC do Mentawai)

  2. Annotation (prático mas intrusivo = GUICE)

Trocar o lookup pelo uma dependencia ao container como vc falou InjectionContainer.newInstance(OutraClasse.class); me parece que não faz sentido…

sergiotaborda

saoj:

entenda que o container de injeção continuará fazendo lookups e que o seu codigo continuará fazendo lookups pois em vez de escrever o codigo
view plaincopy to clipboardprint?

  1. OutraClasse outra = Lookup.lookup(OutraClasse.class);

OutraClasse outra = Lookup.lookup(OutraClasse.class);
vc escreverá
view plaincopy to clipboardprint?

  1. OutraClasse outra = InjectionContainer.newInstance(OutraClasse.class);

OutraClasse outra = InjectionContainer.newInstance(OutraClasse.class);

Que no fim é a mesma coisa. A diferença é que usando o container vc tem injeção configurável.
É a configuração que é o ganho aqui e não a eliminação do lookup.

Acho que vc se enganou aqui. Um container de IoC deve usar Injection por reflection, ou seja, a classe que está recebendo nem vai saber que o container existe. Vai apenas receber a implementação do componente (interface) que precisa.

  1. IoC não é apenas para interfaces. Eu posso injetar classes tb. Na realidade IoC é para injeção de tipos. Quaisquer que eles sejam.
    claro que usar inerfaces tem outras vantagens, mas essas vantagens advem do ppr uso de interfaces e não do IoC em si. Por outro lado, mesmo com classes é possivel alterar a implementação subjacente (seja por herança, ou manipulação de bytecode).

  2. Não conheço nenhum framework onde eu escreva A a = new A(); e o “new” seja intersectado para fazer a injeção. Provavelmente até ha (via AOP ou manipulação de bytecode), mas não é o padrão. O padrão é usar algum tipo de fábrica.

Vc está pensando em IoC para web. Ai vc tem um esquema de objetos à sua disposição para disfarçar a injeção ( como filtros , por exemplo). eu estou falando de IoC em geral num ambiente qualquer, não necessáriamente web. Neste caso vc não pode contar com filtros. As opções são então “envenenar” o new ou usar algum tipo de fabrica/lookup

saoj

Tem razão… Fora do context web o buraco é mais embaixo… Por isso que perguntei o contexto do amigo aí… Não duvido que seja web… :slight_smile:

rruppel

eu perguntei para agregar conhecimento…

então seria num contexto genérico…

mas o projeto q me referia qdo falava do container eh um web…

apesar q tb estou fazendo em casa um projeto desktop para uma loja de açai do meu primo… mas eu resolvi não usar containers para esse projeto… faço tudo na mão… até pq é bem simples…


IoC tem pouco a ver com concorrencia. Qual é o seu contexto? Aplicação web? Aplicação distribuída? Desktop?

Pelo menos numa aplicação web, vc tem os escopos APPLICATION (singleton), SESSION, e REQUEST. Não entendi o que vc quiz dizer com concorrencia e IoC.

eu falei sobre concorrência pelo seguinte:

eu estava usando singleton nessa aplicação desktop para a loja de açai do meu primo e fikei curioso sobre a forma de usar as práticas mais recomendadas hoje de injeção de dependências numa aplicação desktop… então vim perguntar aki no fórum… e lembro de ter guardado q a melhor justificativa e alternativa eram:

  • usar um container leve para a aplicação desktop, pq assim eu ganho flexibilidade… pq se um dia eu mudar essa aplicação para uma aplicação web eu teria sérios problemas com métodos estáticos e singleton (edit: devido á concorrência… hehhee acho q era óbvio mas é bom colocar)

edit2: nossa… q ingrato q fui… os cara fizeram maior discussão aki e eu nem agradeci…

bom… brigadão gente… muitas respostas boas… mas não sei nem se entendi direito tudo o q foi falado aki…

abraços

Criado 14 de janeiro de 2008
Ultima resposta 14 de jan. de 2008
Respostas 10
Participantes 3