Java Dependency Injection design pattern permite-nos remover as dependências codificadas e tornar a nossa aplicação vagamente acoplada, extensível e conservável. Podemos implementar a injeção de dependências em java para mover a resolução de dependências do tempo de compilação para o tempo de execução.,
injeção de dependência de Java
injeção de dependência de Java parece difícil de entender com a teoria, então eu pegaria um exemplo simples e então veremos como usar o padrão de injeção de dependência para alcançar acoplamento solto e extendabilidade na aplicação.
Vamos dizer que temos uma aplicação onde nós consumimos EmailService
para enviar e-mails. Normalmente aplicaríamos isto como abaixo.
EmailService
class holds the logic to send an email message to the recipient email address., Nosso código de aplicação será como abaixo.
O nosso código de cliente que irá usar MyApplication
classe para enviar mensagens de E-mail será como abaixo.
à primeira vista, não parece haver nada de errado com a implementação acima. Mas acima da lógica de código tem certas limitações.
-
MyApplication
class is responsible to initialize the email service and then use it. Isto leva a uma dependência codificada. Se quisermos mudar para algum outro serviço avançado de E-mail no futuro, ele vai exigir alterações de código na classe Myaplication., Isso torna nossa aplicação difícil de estender e se o serviço de E-mail é usado em várias classes, então isso seria ainda mais difícil. - Se queremos estender a nossa aplicação para fornecer um recurso de mensagens adicionais, como SMS ou mensagem do Facebook, então precisaríamos de escrever outra aplicação para isso. Isto envolverá alterações de código nas classes de aplicação e nas classes de clientes também.
- testar a aplicação será muito difícil, uma vez que a nossa aplicação está a criar directamente a instância do serviço de E-mail. Não podemos gozar com estes objectos nas nossas aulas de teste.,
pode-se argumentar que podemos remover o serviço de e-mail de criação da instância de MyApplication
classe por ter um construtor que requer o serviço de e-mail como um argumento.
mas, neste caso, estamos pedindo aplicações clientes ou classes de teste para inicializar o serviço de E-mail que não é uma boa decisão de design.
Agora vamos ver como podemos aplicar o padrão de injeção de dependências java para resolver todos os problemas com a implementação acima., A injeção de dependência em java requer pelo menos o seguinte:
- os componentes de Serviço devem ser projetados com a classe base ou interface. É melhor preferir interfaces ou classes abstratas que definam contratos para os Serviços.as classes de consumidores devem ser escritas em termos de interface de serviço.classes de injetores que inicializarão os serviços e, em seguida, as classes de consumidores.
Java Dependency Injection – Service Components
For our case, we can haveMessageService
that will declare the contract for service implementations.,
package com.journaldev.java.dependencyinjection.service;public interface MessageService {void sendMessage(String msg, String rec);}
Agora vamos supor que temos serviços de E-mail e SMS que implementam as interfaces acima.
nossos serviços de injeção de dependência java estão prontos e agora podemos escrever a nossa classe de consumidores.
Java Dependency Injection – Service Consumer
we are not required to have base interfaces for consumer classes but I will have a interface declaring contract for consumer classes.
package com.journaldev.java.dependencyinjection.consumer;public interface Consumer {void processMessages(String msg, String rec);}
a implementação da minha classe de consumo é a seguinte.
Notice that our application class is just using the service., Ele não inicializa o serviço que leva a uma melhor “separação de preocupações”. Também o uso de interface de serviço nos permite testar facilmente a aplicação, zombando do serviço MessageService e vincular os Serviços em tempo de execução, em vez de tempo de compilação.
Agora estamos prontos para escrever classes de injetores de dependência java que inicializarão o serviço e também classes de consumidores.
Java Dependency Injectors Classes
Let’s have an interface MessageServiceInjector
with method declaration that returns the class.,
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;public interface MessageServiceInjector {public Consumer getConsumer();}
agora para cada serviço, teremos que criar classes de injectores como abaixo.
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;import com.journaldev.java.dependencyinjection.consumer.MyDIApplication;import com.journaldev.java.dependencyinjection.service.EmailServiceImpl;public class EmailServiceInjector implements MessageServiceInjector {@Overridepublic Consumer getConsumer() {return new MyDIApplication(new EmailServiceImpl());}}
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;import com.journaldev.java.dependencyinjection.consumer.MyDIApplication;import com.journaldev.java.dependencyinjection.service.SMSServiceImpl;public class SMSServiceInjector implements MessageServiceInjector {@Overridepublic Consumer getConsumer() {return new MyDIApplication(new SMSServiceImpl());}}
Agora vamos ver como as nossas aplicações cliente irão usar a aplicação com um programa simples.
Como pode ver, as nossas classes de aplicação são responsáveis apenas pela utilização do serviço. As classes de serviço são criadas em injetores. Também se tivermos que ampliar ainda mais a nossa aplicação para permitir mensagens no facebook, teremos que escrever aulas de Serviço e aulas de injector apenas.,a implementação de injeção de dependência resolveu o problema com dependência de código rígido e nos ajudou a tornar a nossa aplicação flexível e fácil de estender. Agora vamos ver com que facilidade podemos testar nossa classe de Aplicação zombando do injector e classes de serviço.
Java Dependency Injection-JUnit Test Case with Mock Injector and Service
As you can see that I am using anonymous classes to mock the injector and service classes and I can easily test my application methods., Estou a usar o JUnit 4 para a classe de teste acima, por isso certifique-se que está no seu caminho de construção do projecto se estiver a correr acima da classe de teste.
temos usado construtores para injetar as dependências nas classes de Aplicação, outra maneira é usar um método setter para injetar dependências nas classes de Aplicação. Para a injeção de dependência do método setter, a nossa classe de aplicação será implementada como abaixo.
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;import com.journaldev.java.dependencyinjection.consumer.MyDIApplication;import com.journaldev.java.dependencyinjection.service.EmailServiceImpl;public class EmailServiceInjector implements MessageServiceInjector {@Overridepublic Consumer getConsumer() {MyDIApplication app = new MyDIApplication();app.setService(new EmailServiceImpl());return app;}}
um dos melhores exemplos de injeção de dependência de setter é a interface Servlet da API Struts2.,
se deve usar a injecção de dependência baseada no construtor ou o setter baseado é uma decisão de design e depende dos seus requisitos. Por exemplo, se minha aplicação não pode funcionar em tudo sem a classe de serviço, então eu preferiria construtor baseado DI ou então eu iria para o método setter baseado DI para usá-lo apenas quando ele é realmente necessário.
injeção de dependências em Java é uma forma de conseguir inversão de controle (COI) em nossa aplicação, movendo objetos ligando-se do tempo de compilação para o tempo de execução., Podemos alcançar o COI através de Padrão de fábrica, padrão de design de método Modelo, Padrão de estratégia e padrão de localização de serviço também.
injeção de dependência de molas, os frameworks Google Guice e Java EE CDI facilitam o processo de injeção de dependências através do uso de API de reflexão Java e anotações java. Tudo o que precisamos é anotar o campo, o construtor ou o método setter e configurá-los em arquivos de configuração xml ou classes.,ção
Alguns dos benefícios do uso de Injeção de Dependência em Java são:
- Separação de Preocupações
- Código Clichê redução na aplicação de aulas, pois todo o trabalho para inicializar dependências é tratado pelo injector componente
- componentes Configuráveis de aplicação faz facilmente expansível.
- o teste de Unidade é fácil com objetos mock
Desvantagens do Java Injeção de Dependência
Java de injeção de Dependência tem algumas desvantagens também:
- Se usado em demasia, pode levar a problemas de manutenção, pois o efeito de alterações são conhecidas em tempo de execução.,a injeção de dependência de
- em java esconde as dependências da classe de serviço que podem levar a erros de tempo de execução que teriam sido capturados no tempo de compilação.
isso é tudo para o padrão de injeção de dependência em java. É bom saber e usá-lo quando estamos no controle dos serviços.