今天在做项目的过程中遇到了
Spring
事务代理类型转换问题
($ProxyXX cannot be cast to
类型
)
,经过网上收集找到了解决方案,特此分享,忘大家多多指教。
一、问题的来由: ( 例子基于 S2SH 框架 )
一、问题的来由: ( 例子基于 S2SH 框架 )
首先晒晒我的项目包的层次结构:
--src
-----com.dao.inter 接口包
-----com.dao.base 父类包,实现接口
-----com.dao 子类包,基础父类
-----com.service.inter 接口包
-----com.service.base 父类包,实现接口
-----com.service子类包,基础父类
-----com.service.action父类包,实现接口
-----com.action子类包,基础父类
-----com.dao.inter 接口包
-----com.dao.base 父类包,实现接口
-----com.dao 子类包,基础父类
-----com.service.inter 接口包
-----com.service.base 父类包,实现接口
-----com.service子类包,基础父类
-----com.service.action父类包,实现接口
-----com.action子类包,基础父类
在
com.dao.inter
包中有一个
IDAO
接口,如下:
public
interface IDAO {
public List findByHql(String hql);
}
public List findByHql(String hql);
}
在
com.dao.base
包下有一个
BaseDao
类,该类实现了接口
IDAO
,如下:
public
class BaseDao
extends HibernateDaoSupport
implements IDAO {
public List findByHql(String hql) {
return this.getHibernateTemplate().find(hql);
}
}
public List findByHql(String hql) {
return this.getHibernateTemplate().find(hql);
}
}
public class UserDao extends BaseDao{
public User loginValidation(String loginName, String loginPassword) {
return null;
}
return null;
}
}
在
com.service.inter
包下有一个
IService
接口,如下:
public
interface IService {
public List findByHql(String hql);
}
public List findByHql(String hql);
}
public
class BaseService
implements IService {
private IDAO dao;
public IDAO getDao() {
return dao;
}
public void setDao(IDAO dao) {
this.dao = dao;
}
private IDAO dao;
public IDAO getDao() {
return dao;
}
public void setDao(IDAO dao) {
this.dao = dao;
}
public List findByHql(String hql) {
return this.getDao().findByHql(hql);
}
}
return this.getDao().findByHql(hql);
}
}
public
class UserService
extends BaseService {
public User loginValidation(String loginName, String loginPassword) {
return ((UserDao) this.getDao()).loginValidation(loginName, loginPassword);
}
}
public User loginValidation(String loginName, String loginPassword) {
return ((UserDao) this.getDao()).loginValidation(loginName, loginPassword);
}
}
<!--
注入sessionFactory到UserDao类 -->
< bean id ="userDao" class ="com.dao.UserDao" >
< property name ="sessionFactory" ref ="sessionFactory" > </ property >
< bean id ="userDao" class ="com.dao.UserDao" >
< property name ="sessionFactory" ref ="sessionFactory" > </ property >
</
bean
>
<!-- 注入UserDao到UserService类 -->
<!-- 注入UserDao到UserService类 -->
<
bean
id
="userService"
class
="com.service.UserService"
>
<
property
name
="dao"
ref
="userDao"
>
</
property
>
</
bean
>
<!-- 注入UserService到UserAction类 -->
<!-- 注入UserService到UserAction类 -->
<
bean
id
="userAction"
class
="com.action.UserAction"
>
<
property
name
="service"
ref
="userService"
>
</
property
>
</
bean
>
并在
Spring
中进行了事务配置,如下:
<!--
配置事务操作 -->
<
bean
id
="transactionManager"
class
="org.springframework.orm.hibernate3.HibernateTransactionManager"
>
<
property
name
="sessionFactory"
ref
="sessionFactory"
/>
</
bean
>
<
tx:advice
id
="txAdvice"
transactionmanager
="transactionManager"
>
<
tx:attributes
>
<
tx:method
name
="add*"
propagation
="REQUIRED"
/>
<
tx:method
name
="insert*"
propagation
="REQUIRED"
/>
<
tx:method
name
="delete*"
propagation
="REQUIRED"
/>
<
tx:method
name
="update*"
propagation
="REQUIRED"
/>
<
tx:method
name
="find*"
read-only
="false"
propagation
="SUPPORTS"
/>
<
tx:method
name
="select*"
read-only
="false"
propagation
="SUPPORTS"
/>
</
tx:attributes
>
</
tx:advice
>
<
aop:config
>
<
aop:pointcut
id
="point"
expression
="execution(* com.dao.*.*(..))"
/>
<
aop:advisor
advice-ref
="txAdvice"
pointcut-ref
="point"
/>
</
aop:config
>
我在
com.action.UserAction(
继承了
BaseAction
类,
BaseAction
又继承了
ActionSupport
类
)
实现了
Action
的操作。在
Action
处理后调用
Service
层的业务代理方法,
Service
层有调用
Dao
层的数据库操作方法,从而实现一个操作。
(
这样分层不知是否合理,忘多多指教
)
问题就出在com.service.UserService类中,如下:
java.lang.ClassCastException: $Proxy56 cannot be cast to com.dao.UserDao at comservice.UserService.loginValidation(UserService.java:27) at com.action.UserAction.login(UserAction.java:26)
于是想为什么会在调用
Dao
层方法时出错,而不是在调用
Service
层方法时出错,结合错误
(
类型转换错误
)
我做了测试,修改了
UserService
类的方法,如下:
输出的结果让我汗颜。如下:
public User loginValidation(String loginName, String loginPassword) {
System.out.println(
this.getDao());
System.out.println(
this.getDao()
instanceof IDAO);
System.out.println(
this.getDao()
instanceof BaseDao);
System.out.println(
this.getDao()
instanceof UserDao);
return ((UserDao)
this.getDao()).loginValidation(loginName, loginPassword);
}
INFO [STDOUT]
com.dao.UserDao@1162695
INFO [STDOUT] true
INFO [STDOUT] false
INFO [STDOUT] false
ERROR [[ default]] Servlet.service() for servlet default threw exception java.lang.ClassCastException: $Proxy56 cannot be cast to com.dao.UserDao at com.service.UserService.loginValidation(UserService.java:27) at com.action.UserAction.login(UserAction.java:26)
INFO [STDOUT] true
INFO [STDOUT] false
INFO [STDOUT] false
ERROR [[ default]] Servlet.service() for servlet default threw exception java.lang.ClassCastException: $Proxy56 cannot be cast to com.dao.UserDao at com.service.UserService.loginValidation(UserService.java:27) at com.action.UserAction.login(UserAction.java:26)
this.getDao()
对象输入的明明是
UserDao
类的实例,但是使用
instanceof
运算符判断输出
false
,现在还没搞懂为什么
(
希望知道的告诉我
)
。按照常理推断,如果是
UserDao
的实例,后面的都应该输出
ture
,因为
UserDao
继承了
BaseDao
,而
BaseDao
实现了
IDAO
,但是该对象只是属于
IDAO
类型。
注:由于字数限制,一次不能写完,所以分为两次编写。该文只是描述了问题的由来。请看下文解决方案。
转载于:https://blog.51cto.com/akudy/697932