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.

Figura 1. Layout.

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