關於Spring事務代理類型轉換問題($ProxyXX cannot be cast to 類型)(一)

    今天在作項目的過程當中遇到了 Spring 事務代理類型轉換問題 ($ProxyXX cannot be cast to 類型 ) ,通過網上收集找到了解決方案,特此分享,忘你們多多指教。  
1、問題的來由:  ( 例子基於 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 類型。
 
   注:因爲字數限制,一次不能寫完,因此分爲兩次編寫。該文只是描述了問題的由來。請看下文解決方案。
相關文章
相關標籤/搜索