Injeção leve com o Google Guice
Veja neste artigo um pouco sobre o framework de injeção de dependência do Google, o Google Guice, além de uma aplicação prática utilizando hibernate, JSF no tomcat.
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:
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
</dependency>
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<Categoria> {
public CategoriaDAO(){
super(Categoria.class);
}
}
@Singleton
public class FilmeDAO extends AbstractDao<Filme> {
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<Session> 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 AbstractDao<T> {
@Inject
protected Session session;
O campo Session receberá injeção a partir do método com anotação @Provides da Classe ServiceModule.
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<Filme> 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 dependência, o Guice não traz inversão de controle, diferente do Spring e do Weld.
Referência:
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Vídeo