Spring Brasil User Group

Fortalecendo a comunidade Spring no Brasil

Jefferson Prestes pergunta:

"Criei um Dao generico, dai só o extendo para cada tabela/model do sistema. Coloco eles no meu applicationContext. Mas na hora que o Spring sobe para inicializa-los ele diz que nao os encontra. Quando crio uma interface para essa classe concreta dai o Spring acha."

"Pq tenho de ficar fazendo uma interface para cada classe sendo que a interface vai ficar vazia? Interfaces 'anemicas', rsrsrsrs. Ou to fazendo algo de errado?"

Spock responde:

"Isto está relacionado ao mecanismo usando por default pelo Spring para criar proxies."

"Por default a anotação <tx:annotation-driven> ativa no Spring o processamento das anotações de demarcação de transação (@Transactional) nos beans envolvendo-os com um proxy criado através de classes do JDK. O mecanismo de proxies do JDK está limitado aos componentes que implementam alguma interface, justamente pq o proxy criado dinamicamente será uma implementação desta interface. Contudo, o Spring é capaz de usar o CGLIB que cria proxies através de 'extends' da implementação do componente (target class), que por herança e polimorfismo tem o mesmo efeito. Mas, o componente não precisa implementar uma interface."

"Portanto, o atributo proxy-target-class da anotação indicada deve ter o valor 'true' para usar o CGLIB. E o jar do CGLIB deve ser adicionado no classpath da aplicação, é claro!".

Tags: cglib, proxy, spock

Exibições: 118

Responder esta

Respostas a este tópico

De qualquer maneira, sempre é bom adotar como prática de desenvolvimento separar a implementação da interface. Até mesmo para um serviço disponibilizado para a aplicação como um DAO. Citei como boa prática de desenvolvimento no blog: 7 Boas Práticas de Desenvolvimento com o Spring Framework.
Obrigado, Spock, nao conhecia esses detalhes da implementacao.
Recebemos um projeto de uma fabrica outro dia que para cada classe havia uma interface e como era sempre uma relacao de 1 para 1 nao vislumbravamos a necessidade disso.
Irei fazer um teste com a CGLIB e dou um retorno.

Ate a proxima,

Jeff
Fui fazer o teste para usar o CGLIB, para não ter de criar Interfaces anemicas que não vejo sentido.

Contudo, recebo esta exception:

Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class br.com.integrator.dao.imp.UsuarioDao]: Common causes of this problem include using a final class or a non-visible class; nested exception is net.sf.cglib.core.CodeGenerationException: java.lang.ClassCastException-->java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:203)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:433)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:299)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1368)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:540)
... 28 more
Caused by: net.sf.cglib.core.CodeGenerationException: java.lang.ClassCastException-->java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at net.sf.cglib.core.ReflectUtils.newInstance(ReflectUtils.java:235)
at net.sf.cglib.core.ReflectUtils.newInstance(ReflectUtils.java:220)
at net.sf.cglib.core.ReflectUtils.newInstance(ReflectUtils.java:216)
at net.sf.cglib.proxy.Enhancer.createUsingReflection(Enhancer.java:640)
at net.sf.cglib.proxy.Enhancer.firstInstance(Enhancer.java:538)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:225)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285)
at org.springframework.aop.framework.Cglib2AopProxy.getProxy(Cglib2AopProxy.java:197)


Mas minha simplezinha classe esta tudo public:

public class UsuarioDao extends DaoGenericoImp implements DaoGenerico {

}

E minha classe de teste:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/applicationContext.xml"})
public class UsuarioDaoTest {


private UsuarioDao usuarioDao;

@Resource
public void setUsuarioDao(UsuarioDao pUsuarioDao) {
this.usuarioDao = pUsuarioDao;
}

public UsuarioDaoTest() {
}

@BeforeClass
public static void setUpClass() throws Exception {
}

@AfterClass
public static void tearDownClass() throws Exception {
}

@Test
public void testLista() {
List lista = usuarioDao.todos();
assertEquals(lista.size(), 1);
}
}


E o xml context do Spring


class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">






class="org.springframework.orm.jpa.JpaTransactionManager">






class="br.com.integrator.dao.imp.UsuarioDao" />

Alguma ideia pq o CGLIB não consegue fazer o proxy da minha classe?

Abs!
Fui realizar o teste.

Eu criei um serviço DAO generico (esta sim implementa uma interface) e depois através de tipos parametrizados eu as extendo e especializo.

Estou recebendo esta exception:


Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class br.com.integrator.dao.imp.UsuarioDao]: Common causes of this problem include using a final class or a non-visible class; nested exception is net.sf.cglib.core.CodeGenerationException: java.lang.ClassCastException-->java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType


Daí fiquei pensando: A CGLIB suporta Parametrized types? Pois o problema parece não estar no Spring.

Abs!

Responder à discussão

RSS

© 2012   Criado por Dr. Spock.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço