[RESOLVIDO] Spring 3.0+Hibernate: Injetando DAO/Repositorio

5 respostas
marvinla

Boa noite a todos!

Comecei a estudar o framework spring. No momento estou estudando a integração com o Hibernate.
Nos testes básicos tudo ok. Porém estou com problemas em injetar dependencias em objetos que são carregados pelo Hibernate, pois como não são carregados pelo Spring, não tem as dependencias injetadas.

public class Pessoa {

	private Long id;
	private String nome;
	private String endereco;
	
	private PessoaDAO dao;
	
	public void setDao(PessoaDAO dao) {
		this.dao = dao;
	}
	
	public void testarDAO() {
		System.out.println("-----> Referencia para o dao");
		System.out.println(dao);
	}

        //outros setters e getters omitidos
	
}

Quando crio um novo objeto pelo Spring a referência ao DAO é injetada. Como fazer para que, quando carregar um objeto da classe Pessoa pelo Hibernate, o DAO também seja injetado?

Obrigado
Marcos Vinícius

5 Respostas

Mikhas

Creio que não da para fazer esse tipo de injeção automaticamente e sinceramente nem acho que muito util.

No lugar de injetar a DAO na sua classe de entidade\VO\Bean\etc, acho melhor você injeta-la no seu controller ou serviço.

L

Existe um truque sujo:

Crie uma classe assim:

public class RichDomainObjectFactory implements BeanFactoryAware {

    private AutowireCapableBeanFactory factory = null;
        
    private static RichDomainObjectFactory singleton = new RichDomainObjectFactory();
    
    public static RichDomainObjectFactory autoWireFactory() {
        return singleton;
    }
    
    public void autowire(Object instance) {
        factory.autowireBeanProperties(instance) 
    }

    public void setBeanFactory(BeanFactory factory) throws BeansException {
        this.factory = (AutowireCapableBeanFactory) factory;
    }
    
}

E declare um bean no Spring assim:

<bean class="my.package.RichDomainObjectFactory" factory-method="autoWireFactory"/>

O que acontece?
A primeira classe é um Singleton, que devolve uma factory. Existem dois métodos: o método setBeanFactory recebe um BeanFactory do Spring, e o método autowire realiza a injeção de qualquer objeto.

A anotação em XML garante a criação de um bean, mas note o pulo do gato, a propriedade “factory-method”, que garante que o Singleton retornado seja transformado em um bean do Spring, consequentemente tendo um BeanFactory injetado. Isso garante que você tenha acesso a um BeanFactory em qualquer lugar da sua aplicação.

Agora vem a parte 2. Crie um interceptor para o Hibernate (estendendo EmptyInterceptor), e sobrescreva o método onLoad(), que é chamado antes da inicialização de um entity do Hibernate.

public class DependencyInjector extends EmptyInterceptor {
    public boolean onLoad(Object entity,
                      Serializable id,
                      Object[] state,
                      String[] propertyNames,
                      Type[] types) {
        RichDomainObjectFactory.autoWireFactory().autowire(entity);
        return false;
    }
}

Declare o interceptor no seu PersistenceUnit

<property name="hibernate.ejb.interceptor" value="my.package.DependencyInjector" />

ou no seu hibernate.cfg.xml

<listener class="my.package.DependencyInjector" />

Agora, anote suas dependências do seu entity com @Autowired, carregue-as pelo Hibernate primeiro, e seu bean estará injetado.

marvinla

Olá Leonardo3001! Obrigado pela resposta.

Leonardo3001:
Existe um truque sujo:

Agora, anote suas dependências do seu entity com @Autowired, carregue-as pelo Hibernate primeiro, e seu bean estará injetado.

No caso, posso configurar a propriedade autowire da tag ?
No mais entendi o pensamento e vou testar assim que chegar em casa.

Mikhas, no exemplo do post, estou injetando um DAO no meu Bean apenas para simplificar o exemplo. Em uma aplicação real, eu injetaria um Repositório (esse sim da camada de domínio).

Obrigado a todos
Marcos Vinícius

fabiofalci

Aqui há uma outra solução usando AOP http://www.jblewitt.com/blog/?p=129

marvinla

Obrigado a todos que responderam, em especial ao Leonardo3001.
No momento, vou utilizar a soluçao sugerida por ele. Aparentemente, uma solução usando AOP ficaria mais independente do Hibernate e dos Interceptos, porém no momento a solução já é suficiente.

Mais uma vez, obrigado a todos!

Marcos Vinícius.

Criado 23 de maio de 2010
Ultima resposta 24 de mai. de 2010
Respostas 5
Participantes 4