A
injeção de dependência é um padrão de desenvolvimento muito
conhecido no mundo java, é ideal principalmente para manter baixo
acoplamento entre diferentes camadas do sistema. Nesse modo o
responsável por injetar esse recurso será o container de injeção
fazendo que algumas vezes o programador não saiba de onde vem tal
recurso. O google apresenta um framework open source para injeção
de dependência é o Google Guice que atualmente está na versão
3.0.
O
principal objetivo do Guice é ser bem leve em comparação ao Spring
além de não precisar de um grande número de xmls ( você consegue
injetar dependência sem usar nenhum! ). Outra informação bastante
interessante é que nessa versão ele implementa a JSR
330.
O Guice também trabalha na injeção de dependência em OSGI,
struts, Swing, JPA e também em Servlets. Um kit completo de injeção
de dependência para o desenvolvimento nas plataformas JEE, JSE e
também android com o RoboGuice.
Para
estar demonstrando os recursos desse framework ID, injeção de
dependência, será realizado um pequeno site web para cadastro de
filmes. Para a persistência será utilizado como ORM o Hibernate com
o banco Postgresql, servidor tomcat versão 7 e na visão uma
implementação do JSF 2.0. Mas vale salientar que o foco do artigo
será o Guice, desse modo, não entrará em detalhes em relação as
tecnologias utilizadas, mas essas possuem informações de fácil
acesso na internet.
Para
adicionar o Guice no projeto com o maven basta adicionar a seguinte
dependência:
com.google.inject guice 3.0
Dessa
forma ele já se encontra pronto para o uso, também é necessário
adicionar as libs do hibernate. Uma vez adicionado as dependências
será criado os objetos para estarem persistindo no banco de dados.
@Entity
@Table(name="categoria")
public class Categoria {
@Id
@GeneratedValue
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "nome")
private String nome;
//getter and setter
}
@Entity
@Table(name="Filme")
public class Filme {
@Id
@GeneratedValue
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "nome")
private String nome;
@ManyToOne
@JoinColumn(name = "Categoria_id", nullable = false)
private Categoria categoria;
@Column
@Temporal(TemporalType.DATE)
private Date lancamento;
@Column
private Integer idadeIndicada;
//getter and setter
}
Uma
vez feito os objeto na qual as informações serão representados, o
próximo passo será a criação do DAO e usaremos o AbstractDao. No
caso de pequeno projeto é desejável que exista apenas uma instância
de cada DAO, e para ajudar nesse problema será usado a anotação
@Singleton.
@Singleton public class CategoriaDAO extends AbstractDao{ public CategoriaDAO(){ super(Categoria.class); } } @Singleton public class FilmeDAO extends AbstractDao { public FilmeDAO(){ super(Filme.class); } }
Outra
anotação importante é o @Inject que quando usado no campo é
responsável por injetar o objeto e quando inserido no método, ele
é executado logo o objeto seja instanciado. Na camada de negócio o
Inject é usado para estar inserindo a dependência da camada DAO.
public class FilmeService {
@Inject
private FilmeDAO filmeDAO;
//codigo de negocio
}
A
classe AbstractModule
do
Google Guice é a classe base para injeção, é nela por exemplo que
podemos definir as implementações de uma interface. Assim é
necessário criar uma classe que extenda do AbstractModule e
sobrescreva o método configure. Outro recurso interessante e só
pode ficar nos módulos é o @Provides, semelhante ao @Produces do
weld, ao adicionado em um método e o mesmo retorne a instancia de um
objeto X, em todas as classes que exista esse objeto como campo com
a anotação @Inject ele chamará desse @Provides, ou seja é uma
notação responsável por estar provendo uma instância em sua
aplicação.
public class ServiceModule extends AbstractModule {
@Override
protected void configure() {
bind(FilmeService.class);
bind(CategoriaService.class);
}
@Provides @Singleton
public SessionFactory provideSessionFactory() {
Configuration configuration = new Configuration();
configuration.configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
return configuration.buildSessionFactory(serviceRegistry);
}
@Provides
public Session provideEntityManager(SessionFactory sessionFactory) {
ThreadLocal threadLocal= new ThreadLocal();
Session session = (Session)threadLocal.get();
session = sessionFactory.openSession();
threadLocal.set(session);
return session;
}
}
No caso da aplicação exemplo a classe ServiceModule que é filha de AbstractModule prover uma sessão do hibernate, assim toda classe que tenha o inject nesse tipo de class o Guice se encarregará de instanciar com o Provides da classe ServiceModule, outra informação é no método que prover o SessionFactory ela também possui a anotação @Singleton, desse modo somente será criado um SessionFactory e esse objeto será injetado em todos os campos do mesmo tipo com a anotação @Inject.
public abstract class AbstractDaoO campo Session receberá injeção a partir do método com anotação @Provides da Classe ServiceModule.{ @Inject protected Session session;
Uma
vez criada essa classe e definido os pontos de injeção o próximo e
ultimo passo é estar realizando o processo de injeção, o próximo
passo será chamar o método createInjector da classe Guice que
criará um Injector, esse por sua vez é o responsável por injetar
os objetos na classe. Para facilitar o processo de injeção foi
criado uma classe abstrata, o AbstractBean, que visa injetar a
dependência de todos os campos além de executar todos os métodos
com o @Inject, desse modo basta criar uma classe que seja filha dessa
classe.
Injector injector = Guice.createInjector(new ServiceModule()); MyClass myclass=injector.getInstance(Myclass.class);
@ManagedBean
@ViewScoped
public class FilmeBean extends AbstractBean {
public Filme filme;
@Inject
private FilmeService filmeService;
@Inject
private CategoriaService categoriaService;
private String titulo;
private String footer;
@Inject
public void init(){
novo();
}
/**
* Salva o filme
*/
public void salvar(){
filme.setCategoria(categoriaService.recuperar(filme.getCategoria().getId()));
if(filme.getId()==null){
filmeService.criar(filme);
}else{
filmeService.atualizar(filme);
}
}
/**
* Realiza a opção de editar um filme
*/
public void editar(){
titulo=VariavelSistema.EDITAR_HEADER;
footer=VariavelSistema.EDITAR_FOOTER;
}
/**
* Realiza a opção de criar um novo filme
*/
public void novo(){
filme=new Filme();
titulo=VariavelSistema.NOVO_HEADER;
footer=VariavelSistema.NOVO_FOOTER;
}
/**
* Lista os filme
* @return a lista de filmes
*/
public List getFilmes(){
return filmeService.listar();
}
//getter e setter do filme, título e footer
}
Desse
modo agora o que falta é a parte da camada de visão com o jsf, para
ajudar com componentes foi adicionado o primefaces que adiciona um
grande número de componentes jsf com Jquery-UI.
Com
isso foi demonstrado um pouco sobre os recursos do google Guice
versão 3.0, que promete ser mais leve que o spring e elimina o
número de xml para a configuração. Um ponto a salientar é que
inversão de controle é diferente de injeção de depenência, o
guice não traz inversão de controle, diferente do Spring e do Weld.
Referências:
Site do Guice: http://code.google.com/p/google-guice/wiki/Motivation?tm=6

Gostei do post, bem claro e objetivo. Vou testar pela manha. Parabéns.
ResponderExcluirEder