Injeção de dependência (Depedency Injection ou apenas DI) é um design pattern utilizado para manter o acoplamento fraco entre classes ou módulos do sistema. O foco principal é fazer com que uma classe não tenha conhecimento de como instanciar um objeto de um tipo do qual é dependente.

Neste post vou apresentar as principais ferramentas utilizadas com essa finalidade em Java, mas antes uma explicação inicial sobre o assunto. Dê uma olhada no código Java abaixo:
public class CaixaMercado {
private CatalogoProdutos catalogoProdutos = new CatalogoProdutosBD();
private List<Produto> itensCompraAtual;
public void iniciarNovaCompra() {
itensCompraAtual = new ArrayList<Produto>();
}
public void produtoPassadoNoLeitor(String codigoDeBarras) throws ProdutoInexistenteException {
if (itensCompraAtual == null) {
throw new IllegalStateException("Compra não foi iniciada.");
}
Produto produto = catalogoProdutos.buscarPeloCodigoBarras(codigoDeBarras);
if (produto == null) {
throw new ProdutoInexistenteException();
}
itensCompraAtual.add(produto);
}
public List<Produto> finalizarCompra() {
// faz algo
List<Produto> itensCompraAnterior = itensCompraAtual;
itensCompraAtual = null;
return itensCompraAnterior;
}
}
Neste exemplo quando um objeto da classe CaixaMercado é instanciado, também é instanciado um objeto do tipo CatalogoProdutosBD (veja na linha 3). Isso torna a classe CaixaMercado dependente da implementação do catálogo lido a partir do banco de dados. Você pode pensar: “Mas nunca vou utilizar outra fonte de dados mesmo.”. E com relação aos testes unitários? E se a classe CatalogoProdutosBD precisasse receber algum parâmetro específico?
Resolvendo “manualmente”
A opção mais simples para resolver este problema é injetar o catálogo de produtos no construtor da classe CaixaMercado. Dessa forma, a classe CaixaMercado fica totalmente desacoplada da implementação de CatalogoProdutos, pois não tem conhecimento se o produto será consultado a partir da base de dados ou arquivo texto, por exemplo. Neste caso, também poderia ser utilizado um método setter para a injeção.
public class CaixaMercado {
private CatalogoProdutos catalogoProdutos;
private List<Produto> itensCompraAtual;
public CaixaMercado(CatalogoProdutos catalogoProdutos) {
this.catalogoProdutos = catalogoProdutos;
}
//...
}
Essa técnica pode ser aplicada para ligar diferentes componentes de sua aplicação com o objetivo diminuir o acoplamento entre eles. Para facilitar a utilização de DI, existem vários frameworks que auxiliam na injeção de objetos através de metadados, como XML e annotations. A seguir apresento as principais opções utilizadas na tecnologia Java.
Spring
O Spring é um framework de IoC (Inversão de Controle) que utiliza a técnica de Injeção de Dependência. Para o código de exemplo, a configuração através de XML seria:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="CatalogoProdutos" class="org.exemplo.di.CatalogoProdutosBD" /> <bean id="CaixaMercado" class="org.exemplo.di.spring.CaixaMercado"> <property name="catalogoProdutos" ref="CatalogoProdutos" /> </bean> </beans>
Nas últimas versões do Spring é possível utilizar apenas annotations no lugar do XML para realizar essa configuração, conforme mostra o código abaixo:
public class CaixaMercado {
@Autowired
private CatalogoProdutos catalogoProdutos;
private List<Produto> itensCompraAtual;
//...
}
@Component
public class CatalogoProdutosBD implements CatalogoProdutos {
@Override
public Produto buscarPeloCodigoBarras(String codigo) {
//...
}
}
O escopo das instâncias gerenciadas pelo Spring podem ser definidos por XML com o atributo scope ou através da annotation @Scope. Os valores possíveis são:
- singleton: Instância única por IoC container
- prototype: Nova instância em cada requisição
- request: Nova instância por requisição HTTP
- session: Nova instância por sessão HTTP
- globalSession: Nova instância por sessão HTTP global (utilizado com portlets)
O Spring também define as seguintes especializações da annonation @Component para identificar diferentes tipos de objetos:
- @Controller
- @Service
- @Repository
Como todo desenvolvedor Java deve saber, o Spring é muito mais do que isso. O objetivo aqui foi apresentar apenas como trabalhar com injeção de dependência com este framework.
Guice
Outra opção é o Guice (pronuncia-se “juice”), que é um framework de injeção de dependências desenvolvido pelo Google. De acordo com o site do projeto, o próprio Google o utiliza em aplicações de missão crítica desde 2006. Abaixo o mesmo exemplo utilizando o Guice:
public class CaixaMercado {
@Inject
private CatalogoProdutos catalogoProdutos;
private List<Produto> itensCompraAtual;
//...
}
Não é necessária nenhuma mudança na classe CatalogoProdutosBD em relação a implementação original. Entretanto, é necessário criar uma classe que define quais são as implementações a serem injetadas:
public class CaixaMercadoModule extends AbstractModule {
@Override
protected void configure() {
bind(CatalogoProdutos.class).to(CatalogoProdutosBD.class);
}
}
O Guice pode ser utilizado em projetos web tornando possível definir o escopo das instâncias dos tipos que são injetados. Para isso são disponibilizadas as seguintes annotations:
- @Singleton
- @SessionScoped
- @RequestScoped
Seam
O JBoss Seam surgiu com o objetivo inicial de realizar uma melhor integração entre o JSF e EJB 3, porém atualmente é um framework muito completo e pode ser utilizado sem EJB ou até mesmo com o Apache Wicket no lugar do JSF, por exemplo. Até a versão 2.x utilizaríamos da seguinte maneira:
public class CaixaMercado {
@In
private CatalogoProdutos catalogoProdutos;
private List<Produto> itensCompraAtual;
//...
}
@Name("catalogoProdutos")
public class CatalogoProdutosBD implements CatalogoProdutos {
@Override
public Produto buscarPeloCodigoBarras(String codigo) {
//...
}
}
A partir do Seam foram propostas e aprovadas a JSR 330: Dependency Injection for Java e a JSR 299: Contexts and Dependency Injection for the Java EE platform. A implementação de referência da JSR 299 é o projeto Weld, que foi baseado no core do Seam. A versão 3 do Seam utiliza o Weld e adiciona funcionalidades especificas que não estão padronizadas.
JSR 330: Dependency Injection for Java
A JSR 330 padroniza as annotations para a injeção de dependências na linguagem Java. As últimas versões do Spring, Guice e Seam são compatíveis com este padrão. Veja abaixo como fica o exemplo:
public class CaixaMercado {
@Inject
private CatalogoProdutos catalogoProdutos;
private List<Produto> itensCompraAtual;
//...
}
@Named("catalogoProdutos")
public class CatalogoProdutosBD implements CatalogoProdutos {
@Override
public Produto buscarPeloCodigoBarras(String codigo) {
//...
}
}
As annotations criadas para injeção de dependências através da JSR 299 estão todas no pacote javax.inject.*. Essas annotations são:
- @Inject: Injeta um objeto em atributo, construtor ou método
- @Named: Qualificador de tipo a ser injetado através de uma string
- @Singleton: Instância única do tipo a ser injetado
- @Qualifier: Identifica annotation que qualifica tipo a ser injetado
- @Scope: Identifica annotation que define um tipo de escopo
Na prática as 2 últimas annotations (@Qualifier e @Scope) são utilizadas pelas implementações (Seam, Guice, etc.) ou quando se deseja realizar alguma customização específica.
JSR 299: CDI for the Java EE platform
Essa JSR descreve várias outras funcionalidades além da injeção de dependências. Para este post vou somente apresentar as annotations que definem os possíveis escopos dos objetos criados para serem injetados, que complementam as especificados pela JSR 330:
- @ApplicationScoped
- @SessionScoped
- @RequestScoped
- @ConversationScoped
EJB 3
Quem utiliza EJB 3 também tem disponível annotations para injeção de dependências. Essas annotations são:
- @EJB: Injeta um session bean
- @PersistenceContext: Injeta o EntityManager gerenciado
- @PersistenceUnit: Injeta o EntityManagerFactory
- @Resource: Injeta recurso disponível na árvore JNDI (Data Source, JMS, etc.)
- @WebServiceRef: Injeta referência para um webservice
Utilizando essas annotations, o container irá realizar o lookup dos objetos e injetá-los. Se fossemos utilizar EJB para o exemplo, poderíamos considerar a implementação de CaixaMercado como um Session Bean Stateful e a implementação do CatalogoProduto como Stateless. Abaixo o código:
@Local
public interface CaixaMercado {
public void iniciarNovaCompra();
public void produtoPassadoNoLeitor(String codigoDeBarras);
public List<Produto> finalizarCompra();
}
@Stateful
public class CaixaMercadoBean implements CaixaMercado {
@EJB
private CatalogoProdutos catalogoProdutos;
private List<Produto> itensCompraAtual;
//...
}
@Local public class CatalogoProdutos public Produto buscarPeloCodigoBarras(String codigo); }
@Stateless
public class CatalogoProdutosBD implements CatalogoProdutos {
@Override
public Produto buscarPeloCodigoBarras(String codigo) {
//...
}
}
Lembrando que também é possível utilizar implementações da JSR 299 em conjunto com o EJB 3.
Outras opções
Abaixo outras opções de ferramentas que podem ser utilizadas para auxiliar a injeção de dependência:
- PicoContainer
- Apache Attic
Apache HiveMind(descontinuado)
Se você souber de mais alguma me avisa que eu adiciono aqui
Conclusão
Nesse post descrevi o que é, por que e como utilizar o conceito Injeção de Dependência em Java. Cada ferramenta apresentada aqui possui muito mais funcionalidades para injeção de objetos e não se limitam a somente essa função. Escolha a(s) sua(s) e bons estudos!
Referências
- Inversion of Control Containers and the Dependency Injection pattern – Martin Fowler
- Spring Framework Reference: The IoC container
- Javadoc Spring 3.0.x
- Spring 3.0 and JSR 330: Using @Named
- Google Guice User’s Guide: Getting Started
- Javadoc Google Guice
- Seam 3 Reference Guide
- JSR 330 – Java Community Process
- Javadoc JSR 330
- JSR 299 – Java Community Process
- Javadoc JSR 299
- Dependency Injection in EJB 3
- Exemplo de cadastro com o JBoss Seam

Acompanhe este blog
7 Responses to “Injeção de Dependência em Java”
não intendi cara a verdadeira vantagem da DI.
Mateus,
Como explico no início do post, o objetivo é diminuir o acoplamento entre classes e camadas da sua aplicação. Isso é uma boa prática de programação porque torna o código mais reaproveitável e de fácil manutenção. Além disso, ajuda na implementação de testes unitários por ficar mais fácil de isolar cada unidade a ser testada.
Recomendo a leitura sobre o conceito “Baixo acoplamento e alta coesão” e sobre “Design Patterns”.
Qualquer duvida manda aí.
Abraço.
Muito bom artigo parabéns!!!!
Obrigado, Fernando!
Abraço
on janeiro 19th, 2012 at 8:32 #
[...] ideal neste caso seria substituir o método estático por uma Injeção de Dependência, porém isso não é possível se você estiver utilizando uma API ou framework que tenha uma [...]
Muito bom o artigo Victor. Parabéns!
Valeu, Aécio! Abraços.