$ProxyXX cannot be cast to 类型

今天在做项目的过程中遇到了Spring事务代理类型转换问题($ProxyXX cannot be cast to 类型),经过网上收集找到了解决方案,特此分享,忘大家多多指教。 
一、问题的来由: (例子基于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包中有一个IDAO接口,如下:
public  interface IDAO {   
    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);
    }
}
    在com.dao包下有一个UserDao类,该类继承了父类BaseDao,如下:
public class UserDao extends BaseDao{
    public User loginValidation(String loginName, String loginPassword) {
         return  null;
    }
}
    在com.service.inter包下有一个IService接口,如下:
public  interface IService {
    public List findByHql(String hql);
}
    在com.service.base包下有一个BaseService类,该类实现了接口IService,如下:
public  class BaseService  implements IService {
    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);
    }
}
    在com.service包下有一个UserService类,该类继承了父类BaseService,如下:
public  class UserService  extends BaseService {
    public User loginValidation(String loginName, String loginPassword) {
         return ((UserDao) this.getDao()).loginValidation(loginName, loginPassword);
    }
}
     com.action包和这个差不多的,不用多说了。在Spring配置文件中实现对象注入,如下:
<!--  注入sessionFactory到UserDao类 -->
< bean  id ="userDao"  class ="com.dao.UserDao" >
    < property  name ="sessionFactory"  ref ="sessionFactory" > </ property >
</ bean >
<!--  注入UserDao到UserService类 -->
< bean  id ="userService"  class ="com.service.UserService" >
    < property  name ="dao"  ref ="userDao" > </ property >
</ bean >
<!--  注入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)
    this.getDao()对象输入的明明是UserDao类的实例,但是使用instanceof运算符判断输出false,现在还没搞懂为什么(希望知道的告诉我)。按照常理推断,如果是UserDao的实例,后面的都应该输出ture,因为UserDao继承了BaseDao,而BaseDao实现了IDAO,但是该对象只是属于IDAO类型。

二、解决方案
      后来在网上搜了一下,这样的问题很多,但是正真的解决方案并不多。参考http://mopishv0.blog.163.com/blog/static/54455932200911118572079写道
      spring的文档中这么写的:Spring AOP部分使用JDK动态代理或者CGLIB来为目标对象创建代理,如果被代理的目标对象实现了至少一个接口,则会使用JDK动态代理。所有该目标类型实现的接口都将被代理。若该目标对象没有实现任何接口,则创建一个CGLIB代理。使用beanNameAutoProxyCreator来进行事务代理的话,他的proxyTargetClass这个属性设置为false(默认是false),即使用JDK动态代理,如果你的service类没有实现接口的话,就会报类型转换错误。
    解决办法有
    1
、给service类添加一个接口iService,让service类实现它,则创建代理类时使用JDK动态代理就不会出现问题
    2、设置beanNameAutoProxyCreatorproxyTargetClass属性为true,意思是强制使用CGLIB代理,前提是你已经将CGLIB包加入到项目中
    推敲了很长时间,因为之前Spring事务用到的并不多,所以不是很了解。
    第一种方法修改UserDao类也实现IDAO接口,但是没有解决。照样报错....
    于是使用了第二种方案,修改了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>
<!-- 注意下面的配置 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
     注意:最后一行配置信息。
     这样之后就解决了,而且测试结果如下:
INFO [STDOUT] com.dao.UserDao@13ba812
INFO [STDOUT] true
INFO [STDOUT] true
INFO [STDOUT] true
    又学了一招,很好很强大。。。接着要好好研究一下JDK动态代理和CGLIB代理(cglib.jarasm.jar)
CSVReader$InvalidCsvFileFormat cannot be cast to...是一个错误类型的转换异常。根据引用,CSVReader使用BufferedReader进行数据的读取操作,而不是使用MappedByteBuffer。BufferedReader在处理小于100MB的数据时,性能表现较好。然而,当遇到这个错误时,可能是由于CSV文件的格式不正确导致的。由于缺少具体的错误信息,我无法提供更具体的解决方案。建议您检查CSV文件的格式是否符合预期,确保每一行的数据都符合要求的格式,并尝试使用适当的异常处理机制来处理转换异常。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [CsvReader:CsvReader](https://download.csdn.net/download/weixin_42109545/18760761)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [spark中处理dataframe往往遇到”...cannot be cast to ...”这种数据不匹配的问题](https://blog.csdn.net/qq_35022142/article/details/79800394)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值