代理不能转换为CLASS [英] Proxy cannot be cast to CLASS

查看:139
本文介绍了代理不能转换为CLASS的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring为使用Hibernate的DAO类专门连线依赖关系,但我遇到了一个令我困惑的异常:

$ Proxy58无法转换为UserDao



我的DAO配置如下:

 < bean id =userDaoclass =com.domain.app.dao.UserDao> 
< property name =sessionFactoryref =sessionFactory/>
< / bean>

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



接口:

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

抽象基类:

 公共抽象类BaseDao实现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);
返回用户;
}

}

下面会引发上面提到的异常:



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



然而,这不会抛出异常:



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

如果任何人都可以提供任何帮助或指导,说明发生这种情况的原因,我会非常感激。

解决方案

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



您可以使用< tx:annotation-driven proxy-target-class =true/> 指示Spring使用代理类的实际子类的CGLIB代理,但我认为最好的做法是对接口进行编程。如果您需要访问代理类中的某些未在其中某个接口中声明的方法,则应首先问自己,为什么会出现这种情况?

(另外,在上面的代码中没有在 UserDao 中引入了新方法,因此将bean强制转换为此具体实现类型没有意义。)



在官方 Spring reference


I'm using Spring for wiring dependencies specifically for DAO classes that use Hibernate, but I'm getting an exception that has me puzzled:

$Proxy58 cannot be cast to UserDao

My DAO is configured as follows:

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

And I have an interface, abstract base class and a final implementation as follows.

Interface:

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

Abstract Base Class:

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

}

Implementation:

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

}

The following throws the exception mentioned above:

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

This, however, does not throw an exception:

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

If anyone can offer any assistance or guidance as to why this exception is happening, I would be very appreciative.

解决方案

Spring uses JDK dynamic proxies by default ($Proxy58 is one of them), that can only proxy interfaces. This means that the dynamically created type $Proxy58 will implement one or more of the interfaces implemented by the wrapped/target class (UserDao), but it won't be an actual subclass of it. That's basically why you can cast the userDao bean to the Dao interface, but not to the UserDao class.

You can use <tx:annotation-driven proxy-target-class="true"/> to instruct Spring to use CGLIB proxies that are actual subclasses of the proxied class, but I think it's better practice to program against interfaces. If you need to access some methods from the proxied class which are not declared in one of it's interfaces, you should ask yourself first, why this is the case?
(Also, in your code above there are no new methods introduced in UserDao, so there is no point in casting the bean to this concrete implementation type anyway.)

See more about different proxying mechanisms in the official Spring reference.

这篇关于代理不能转换为CLASS的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆