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.

Layout
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: