4. Injeção de dependência
A injeção de dependência pode ser considerada uma consequência da inversão de controle. Vamos ilustrar isso com um novo exemplo. Consideremos a seguinte aplicação web de três camadas:
![]() |
Suponhamos que o acesso à camada DAO seja controlado pela interface [IArticlesDao] estudada anteriormente e que toda a aplicação seja uma aplicação web para compras de artigos na internet. Os artigos são aqueles gerenciados pela camada [Dao]. Supõe-se que o acesso à camada de negócios seja controlado pela seguinte interface:
Public Interface IArticlesDomain
' comprar um carrinho de compras
Sub acheter(ByVal panier As Panier)
' obter a lista de itens
Function getAllArticles() As IList
' obter um artigo específico
Function getArticleById(ByVal idArticle As Integer) As Article
' para registrar os erros
ReadOnly Property erreurs() As ArrayList
End Interface
Não vamos nos deter no significado dos diferentes métodos. Basta observar que o método [getAllArticles], que deve obter a lista de todos os artigos à venda, precisa ter acesso aos dados. Para obtê-los, ele deve acessar a interface [IArticlesDao]. A estrutura básica de uma classe de implementação da interface [IArticlesDomain] poderia ser semelhante a esta:
Imports istia.st.articles.dao
...
Namespace istia.st.articles.domain
Public Class AchatsArticles
Implements IArticlesDomain
'campos privados
Private _articlesDao As IArticlesDao
Private _erreurs As ArrayList
' construtor
Public Sub New(ByVal articlesDao As IArticlesDao)
_articlesDao = articlesDao
End Sub
...
End Class
End Namespace
Como já mencionamos, alguns métodos da interface da camada de negócios precisam solicitar dados à camada [Dao]. Portanto, nossa classe de implementação [AchatsArticles] da interface [IArticlesDomain] precisa de uma referência a uma implementação da interface [IArticlesDao]. No exemplo acima, o campo privado [_articlesDao] é essa referência. Ela é fornecida no momento da construção de um objeto [AchatsArticles].
Suponhamos que a classe [AchatsArticles] tenha sido criada e que queiramos testá-la com um teste do tipo [Nunit]. Vamos criá-lo para que utilize um arquivo de configuração do Spring:
...
Imports Spring.Objects.Factory.Xml
Imports System.IO
...
<TestFixture()> _
Public Class NunitSpringTestArticlesDomain
' o objeto a ser testado
Private articlesDomain As IArticlesDomain
<SetUp()> _
Public Sub init()
' recuperar uma instância do criador de objetos do Spring
Dim factory As XmlObjectFactory = New XmlObjectFactory(New FileStream("spring-config-domain.xml", FileMode.Open))
' é solicitada a instanciação do objeto DAO “artigos”
articlesDomain = CType(factory.GetObject("articlesdomain"), IArticlesDao)
End Sub
...
End Class
Qual seria o conteúdo do arquivo de configuração [spring-config-domain.xml] do Spring? Ele poderia ser o seguinte:
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE objects PUBLIC "-//SPRING//DTD OBJECT//EN"
"http://www.springframework.net/dtd/spring-objects.dtd">
<objects>
<description>Gestion d'une table d'articles</description>
<!-- a classe de implementação da interface IArticlesDao -->
<object id="articlesdao" type="istia.st.articles.dao.ArticlesDaoPlainODBC, articlesdao">
<constructor-arg index="0">
<value>odbc-firebird-articles</value>
</constructor-arg>
<constructor-arg index="1">
<value>SYSDBA</value>
</constructor-arg>
<constructor-arg index="2">
<value>masterkey</value>
</constructor-arg>
</object>
<!-- a classe de implementação da interface IArticlesDomain -->
<object id="articlesdomain" type="istia.st.articles.domain.AchatsArticles, articlesdomain">
<constructor-arg index="0">
<ref object="articlesdao" />
</constructor-arg>
</object>
</objects>
Este arquivo é o mesmo já utilizado para instanciar o singleton do tipo [IArticlesDao] da camada [Dao], ao qual foi adicionado o código para instanciar o singleton do tipo [IArticlesDomain] da camada de negócios. Como ele será construído?
- Um código externo solicita ao Spring uma referência ao singleton denominado “articlesdomain” no arquivo de configuração. Esse é o caso do método [init] da nossa classe de teste:
<SetUp()> _
Public Sub init()
' obtém-se uma instância do criador de objetos do Spring
Dim factory As XmlObjectFactory = New XmlObjectFactory(New FileStream("spring-config-domain.xml", FileMode.Open))
' solicita-se a instanciação do objeto DAO de artigos
articlesDomain = CType(factory.GetObject("articlesdomain"), IArticlesDao)
End Sub
- O Spring encontra, em seu arquivo de configuração, a definição do singleton em questão. Ele descobre que, para instanciá-lo, precisa de outro singleton chamado “articlesdao”:
<object name="articlesdomain" class="istia.st.articles.domain.AchatsArticles, articlesdomain">
<constructor-arg index="0">
<ref object="articlesdao" />
</constructor-arg>
</object>
- O Spring então instanciará o singleton “articlesdao”. Já explicamos como isso ocorre.
- Feito isso, ele pode instanciar o singleton “articlesdomain” e retornar uma referência a ele para o código que o solicitou.
Esse mecanismo poderia ser esquematizado da seguinte forma:
![]() |
Vemos que o Spring gerenciou a dependência que o singleton “articlesdomain” tinha em relação ao singleton “articlesdao”. Para utilizar o Spring dessa forma, precisamos criar uma classe com um construtor que aceitasse como argumento o singleton dependente:
Imports istia.st.articles.dao
...
Namespace istia.st.articles.domain
Public Class AchatsArticles
Implements IArticlesDomain
'campos privados
Private _articlesDao As IArticlesDao
' construtor
Public Sub New(ByVal articlesDao As IArticlesDao)
_articlesDao = articlesDao
End Sub
...
End Class
End Namespace
O termo “injeção de dependência” abrange tanto:
- a maneira específica de construir as classes a serem instanciadas com base em suas dependências
- a maneira como o Spring gerencia essas dependências no momento da instanciação dessas classes

