Para compreendermos porque foi necessário criar uma especificação para injeção de dependências em Java, vamos ver que benefícios trás uma especificação. Uma especificação pode ser comparada a um contrato, um modelo a ser seguido. Este contrato diz o que, mas não como uma determinada funcionalidade deve ser implementada na plataforma Java. Para ficar mais claro, o nosso artigo fala sobre a JSR-330, injeção de dependências baseada em anotações. Essa especificação determina o que o deve ser seguido para injetar dependências em Java. Os frameworks devem seguir esse padrão, visando manter a portabilidade entre eles.
Vamos supor que estamos utilizando um framework, como o Spring, e temos a necessidade de migrar para um outro, como o Guice. Antes da especificação, teríamos problemas, pois cada framework implementava a injeção de dependência de uma maneira, conforme pode ser visto na Figura 1.
Figura 1: Esquema de funcionamento dos frameworks
A Figura 2 mostra a vantagem de se seguir uma especificação. Há portabilidade entre os frameworks, bastando escolher a implementação desejada. Para ficar mais claro, vamos à nossa aplicação.
Figura 2: Frameworks com a especificação
Os mecanismos do Spring para implementar injeção de dependência, até a versão 2.5, não seguiam a especificação JSR-330. A partir da versão 3.0 do Spring, as anotações utilizadas são baseadas na especificação Java para injeção de dependências. A Tabela 1 mostra as anotações utilizadas antes da especificação, e a Tabela 2 mostra as anotações utilizadas pela especificação JSR-330:
@Component | Anotação genérica para qualquer componente gerenciado pelo Spring. Esta anotação faz com que o bean registrado no Spring possa ser utilizado em qualquer bean, seja ele um serviço, um DAO, um controller, etc. No nosso exemplo, ele será responsável por um Bean que representa uma entidade. |
@Repository | Anotação que serve para definir uma classe como pertencente à camada de persistência. |
@Service | Anotação que serve para definir uma classe como pertencente à camada de Serviço da aplicação. |
@Autowired | A anotação @ Autowired fornece controle sobre onde e como a ligação entre os beans deve ser realizada. Pode ser usado para em métodos setter, no construtor, em uma propriedade ou métodos com nomes arbitrários e / ou vários argumentos. |
Tabela 1: Anotações do Spring usadas na aplicação
@Named | Ao invés de @Component do Spring |
@Inject | Ao invés de @Autowired do Spring |
Tabela 2: Anotações para Injeção de Dependência em Java
Bom, agora é começar o projeto. Para isso, abra o IDE Eclipse e crie um novo Java Project. Após isso, crie um arquivo XML simples, com nome de spring.xml, conforme pode ser visto na Listagem 1. Este arquivo será o responsável pela configuração do Spring Framework. Após isso, vamos criar uma classe Java, nomeando-a para App.java. Esta classe é a principal de nossa aplicação, e é responsável por colocar o Spring dentro do contexto da aplicação, ou seja, permite que o Spring trabalhe por nós. Pedimos então ao Spring que inicie sua execução a partir do método save(), presente na classe ClienteService, conforme pode ser visto na Listagem 2.
Listagem 1: Arquivo de configuração do Spring Framework
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:component-scan base-package="br.com" />
</beans>
Listagem 2: Classe que insere o Spring no contexto da aplicação (App.java)
package br.com.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import br.com.cliente.service.ClienteService;
public class App {
public static void main( String[] args ) {
ApplicationContext context = new ClassPathXmlApplicationContext(
new String[] {"spring.xml"});
ClienteService cliente = (ClienteService)context.getBean("clienteService");
cliente.save();
}
}
A classe ClienteService tem duas dependências gerenciadas e injetadas pelo Spring. São elas, a classe Cliente, apresentada na Listagem 3 e a classe ClienteDao, mostrada na Listagem 5. A classe ClienteService apresenta algumas anotações. A anotação @Service, representa esta classe como se fosse um serviço. Já as anotações @Inject, permitem que o Spring injete as dependências nesta classe, conforme pode ser visto na Listagem 3.
Listagem 3: Classe ClienteService.java
package br.com.cliente.service;
import javax.inject.Inject;
import javax.inject.Named;
import br.com.cliente.dao.ClienteDao;
import br.com.cliente.entity.Cliente;
@Named
public class ClienteService {
@Inject
ClienteDao clienteDAO;
@Inject
Cliente cliente;
public void save() {
cliente.setNome("Leonel Messi");
System.out.println("Cliente foi manipulado no Service");
clienteDAO.save(cliente);
}
}
Listagem 4: Classe Cliente.java
package br.com.cliente.entity;
import javax.inject.Inject;
import javax.inject.Named;
@Named
public class Cliente {
private String nome;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
Listagem 5: Classe ClienteDao.java
package br.com.cliente.dao;
import org.springframework.stereotype.Repository;
import br.com.cliente.entity.Cliente;
@Repository
public class ClienteDao
{
public void save(Cliente cliente) {
System.out.println("Cliente salvo no Dao: "+cliente.getNome());
}
}
Bom, apesar de apresentarmos somente as anotações básicas da especificação Java para injeção de dependências, vimos que foi possível diminuir o acoplamento com o Framework Spring ao se utilizar desta especificação. Bom pessoal, obrigado e até um próximo artigo, abraço.