代理无法转换为CLASS

mch*_*ler 24 spring hibernate casting

我正在使用Spring专门为使用Hibernate的DAO类连接依赖项,但是我得到了一个令我困惑的异常:

$ Proxy58无法强制转换为UserDao

我的DAO配置如下:

<bean id="userDao" class="com.domain.app.dao.UserDao">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
Run Code Online (Sandbox Code Playgroud)

我有一个接口,抽象基类和最终实现如下.

接口:

public interface Dao {
    public void save(Object object);
    public Object load(long id);
    public void delete(Object object);
    public void setSessionFactory(SessionFactory sessionFactory);
}
Run Code Online (Sandbox Code Playgroud)

抽象基类:

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();
    }

}
Run Code Online (Sandbox Code Playgroud)

执行:

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

以下引发了上述异常:

UserDao dao =(UserDao)context.getBean("userDao");

但是,这不会引发异常:

Dao dao =(Dao)context.getBean("userDao");

如果有人可以提供任何有关此例外情况的帮助或指导,我将非常感激.

zag*_*gyi 50

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

您可以使用它<tx:annotation-driven proxy-target-class="true"/>来指示Spring使用作为代理类的实际子类的CGLIB代理,但我认为对接口进行编程是更好的做法.如果你需要从代理类访问一些未在其中一个接口中声明的方法,你应该首先问自己,为什么会这样?
(另外,在上面的代码中没有引入新的方法UserDao,所以无论如何都没有必要将bean转换为这个具体的实现类型.)

在官方Spring参考中查看有关不同代理机制的更多信息.

  • "......你应该先问问自己,为什么会这样?" - 一个例子是在单元测试中测试内部方法.我想测试一个特定的实现,而不是接口.无论如何,很棒的答案! (6认同)

Unc*_*roh 6

我正在编写单元测试,并且需要能够为某些调用存根DAO.Per This guys post:http: //www.techper.net/2009/06/05/how-to-acess-target-object-behind-a-spring-proxy/ 我用他提供的方法:

@SuppressWarnings({"unchecked"})
protected <T> T getTargetObject(Object proxy, Class<T> targetClass) throws Exception {
  if (AopUtils.isJdkDynamicProxy(proxy)) {
    return (T) ((Advised)proxy).getTargetSource().getTarget();
  } else {
    return (T) proxy; // expected to be cglib proxy then, which is simply a specialized class
  }
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以使用代理轻松调用它并获取代理后面的对象,并根据需要直接操作其中的对象.