26

特に Hibernate を使用する DAO クラスの依存関係を配線するために Spring を使用していますが、困惑する例外が発生しています。

$Proxy58 は UserDao にキャストできません

私のDAOは次のように構成されています:

<bean id="userDao" class="com.domain.app.dao.UserDao">
    <property name="sessionFactory" ref="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);
}

抽象基本クラス:

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 dao = (Dao) context.getBean("userDao");

この例外が発生する理由について誰かが支援またはガイダンスを提供できる場合は、非常に感謝しています.

4

2 に答える 2

53

Spring はデフォルトでJDK 動的プロキシ$Proxy58を使用し (はそのうちの 1 つです)、プロキシ インターフェイスのみを使用できます。これは、動的に作成された型$Proxy58が、ラップされた/ターゲット クラス ( ) によって実装された 1 つ以上のインターフェイスを実装することを意味しUserDaoますが、実際のサブクラスにはなりません。これが基本的に、userDaoBean をDao interfaceにキャストできるが、UserDao classにはキャストできない理由です。

を使用して、プロキシされたクラスの実際のサブクラスである CGLIB プロキシを使用するように Spring に指示できますが<tx:annotation-driven proxy-target-class="true"/>、インターフェイスに対してプログラミングする方が良いと思います。インターフェイスの 1 つで宣言されていない、プロキシされたクラスからいくつかのメソッドにアクセスする必要がある場合は、最初に自問する必要があります。
(また、上記のコードには で導入された新しいメソッドがないUserDaoため、この具体的な実装タイプに Bean をキャストしても意味がありません。)

公式のSpring リファレンスで、さまざまなプロキシ メカニズムの詳細を参照してください。

于 2013-04-16T22:06:03.440 に答える
10

私は単体テストを書いていて、いくつかの呼び出しのために DAO をスタブ化できるようにする必要がありました。この男の投稿ごと: 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
  }
}

次に、プロキシを使用して簡単に呼び出し、プロキシの背後にあるオブジェクトを取得し、必要に応じてそのオブジェクトを直接操作できます。

于 2016-06-02T23:26:56.013 に答える