我正在使用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中了解有关不同代理机制的更多信息。