Hibernate + Spring + Struts中的一个常见错误
2007-10-06 09:36
639 查看
使用Spring中的AOP技术代理了Service(实现声明式事务管理),然后将Service通过IoC注入给Action.未加入Struts时一切正常,但是加入Struts后出错,提示信息大意为无法将被代理的Service对象注入给Action,异常为ClassCastException.
【分析原因】
ClassCastException表明这是一个类型不匹配错误,再看详细的出错信息:"Can't convert $Proxy1 to com.xaccp.XxxService"(大体是这个意思,原文记不清了),说明在Action中需要的类型为com.xaccp.XxxService,而实际传入的是$Proxy1。
接下来应该想到Service对象是被Spring代理的,Spring中有两种实现代理的方法:JDK提供的动态代理和CGLIB。
CGLIB的实现原理是动态生成目标类(Target)的子类,如果一个类采用CGLIB代理的,生成的子类类名一般为com.xaccp.XxxService$$EnhanceByCGLIB$xxxx的格式,并且根据父子类转换的规则,在要求目标类的地方,如果传入生成的代理类不会发生ClassCastException异常。
而动态代理的实现原理是动态生成一个与目标类显示相同接口的类,生成类类名就是$Proxy1这样的格式,在要求目标类的地方,如果传入生成的代理类就会发生上面的错误。
再看学生写的Service类,果然实现了一个接口,那么默认的情况下,如果类存在接口,Spring就会采用动态代理来实现AOP,于是发生了上面的错误。
【解决方案】
分析清楚原因以后解决方案就出来了:
最简单的一种方案就是去掉Service实现的接口,那么Spring会采用CGLIB来实现AOP。但是这个方案显然破坏了代码的结构
最应该采取的一种方案是在Action中不要直接将属性声明为Service类,而是声明为其接口,这样Spring就可以将实现了同样接口的$Proxy1代理类注入进来。并且体现了面向接口编程的原则。
还有一种方案就是在设置代理时指明proxyTargetClass属性为true,强制Spring采用CGLIB进行代理,如下所示:
<bean id="service" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target">
<ref bean="dummyService"/>
</property>
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionManager">
<ref bean="tm"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
文章引用自:
【分析原因】
ClassCastException表明这是一个类型不匹配错误,再看详细的出错信息:"Can't convert $Proxy1 to com.xaccp.XxxService"(大体是这个意思,原文记不清了),说明在Action中需要的类型为com.xaccp.XxxService,而实际传入的是$Proxy1。
接下来应该想到Service对象是被Spring代理的,Spring中有两种实现代理的方法:JDK提供的动态代理和CGLIB。
CGLIB的实现原理是动态生成目标类(Target)的子类,如果一个类采用CGLIB代理的,生成的子类类名一般为com.xaccp.XxxService$$EnhanceByCGLIB$xxxx的格式,并且根据父子类转换的规则,在要求目标类的地方,如果传入生成的代理类不会发生ClassCastException异常。
而动态代理的实现原理是动态生成一个与目标类显示相同接口的类,生成类类名就是$Proxy1这样的格式,在要求目标类的地方,如果传入生成的代理类就会发生上面的错误。
再看学生写的Service类,果然实现了一个接口,那么默认的情况下,如果类存在接口,Spring就会采用动态代理来实现AOP,于是发生了上面的错误。
【解决方案】
分析清楚原因以后解决方案就出来了:
最简单的一种方案就是去掉Service实现的接口,那么Spring会采用CGLIB来实现AOP。但是这个方案显然破坏了代码的结构
最应该采取的一种方案是在Action中不要直接将属性声明为Service类,而是声明为其接口,这样Spring就可以将实现了同样接口的$Proxy1代理类注入进来。并且体现了面向接口编程的原则。
还有一种方案就是在设置代理时指明proxyTargetClass属性为true,强制Spring采用CGLIB进行代理,如下所示:
<bean id="service" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target">
<ref bean="dummyService"/>
</property>
<property name="proxyTargetClass">
<value>true</value>
</property>
<property name="transactionManager">
<ref bean="tm"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
文章引用自:
相关文章推荐
- SpringMVC+Hibernate 一个经典的由懒加载机制引发的错误
- [征求意见]我想做一个spring+struts+hibernate+ajax的分页程序。大家认为怎么样?
- 使用Spring、Hibernate、Struts的一些错误总结(转)
- Spring,hibernate,struts常见的面试笔试题汇总
- 使用Spring、Hibernate、Struts的一些错误总结
- spring+struts+hibernate常见异常总结
- Spring,struts,hibernate常见的面试笔试题汇总(1)
- 最近用hibernate3+spring2.5+freemarker2.4做了一个案例出现错误!
- struts+hibernate+spring一个入门的实用例子(转)
- struts+hibernate+spring一个入门的实用例子(上)
- Spring,struts,hibernate常见的面试笔试题汇总(2)
- 使用Spring、Hibernate、Struts的一些错误总结(不断补充)
- idea整合struts和spring和hibernate时候的导jar错误:Unable to load configuration. - action -
- Spring+Hibernate+Struts技术的一个分页程序
- 使用Spring、Hibernate、Struts的一些错误总结(不断补充)
- struts+hibernate+spring一个入门的实用例子(下)
- Struts2+hibernate+spring整合时错误
- 这是一个结合了Struts、Spring、Hibernate的登录完整
- spring+struts+hibernate常见异常总结--邵京国
- Spring+Hibernate+Struts技术的一个分页程序