我正在使用Spring来为专门用于使用Hibernate的DAO类的依赖关系进行接线,但是却遇到了一个让我感到困惑的异常:

$ Proxy58无法转换为UserDao

我的DAO的配置如下:

<bean id="userDao" class="com.domain.app.dao.UserDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

我有一个接口(interface),抽象基类和最终实现,如下所示。

接口(interface):
public interface Dao {
    public void save(Object object);
    public Object load(long id);
    public void delete(Object object);
    public void setSessionFactory(SessionFactory sessionFactory);
}

抽象基类:
public abstract class BaseDao implements Dao {

    private SessionFactory sessionFactory;

    @Transactional
    @Override
    public void save(Object object) {
        PersistentEntity obj = (PersistentEntity) object;
        currentSession().saveOrUpdate(obj);
    }

    @Transactional
    @Override
    public abstract Object load(long id);

    @Transactional
    @Override
    public void delete(Object object) {
        // TODO: this method!
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public Session currentSession() {
        return sessionFactory.getCurrentSession();
    }

}

实现方式:
public class UserDao extends BaseDao implements Dao {

    @Transactional(readOnly=true)
    @Override
    public Object load(long id) {
        Object user = currentSession().get(User.class, id);
        return user;
    }

}

以下引发上述异常:

UserDao dao =(UserDao)context.getBean(“userDao”);

但是,这不会引发异常:

刀=(Dao)context.getBean(“userDao”);

如果有人可以提供任何帮助或指导,以说明为什么发生此异常,我将不胜感激。

最佳答案

Spring默认使用JDK dynamic proxies($Proxy58是其中之一),它只能代理接口(interface)。这意味着动态创建的$Proxy58类型将实现由包装/目标类(UserDao)实现的一个或多个接口(interface),但它不是它的实际子类。这就是为什么可以将userDao bean强制转换为Dao接口(interface)而不是UserDao类的原因。

您可以使用<tx:annotation-driven proxy-target-class="true"/>指示Spring使用CGLIB代理,它们是代理类的实际子类,但是我认为针对接口(interface)进行编程是更好的做法。如果您需要访问代理类中未在其接口(interface)之一中声明的某些方法,则应首先问自己,为什么会这样?
(此外,在上面的代码中,UserDao中没有引入新的方法,因此将bean强制转换为这种具体的实现类型毫无意义。)

在官方Spring reference中了解有关不同代理机制的更多信息。

10-08 01:19