2013-04-16 9 views
21

I Frühling bin mit der Verdrahtung Abhängigkeiten speziell für DAO-Klassen, die Hibernate verwenden, aber ich bin eine Ausnahme erhalten, die hat mich verwirrt:Proxy kann nicht für die Klasse geworfen werden

$ Proxy58 kann nicht auf UserDao gegossen werden

Mein DAO ist wie folgt konfiguriert:

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

und ich habe eine Schnittstelle, abstrakte Basisklasse und eine endgültige Umsetzung wie folgt.

Schnittstelle:

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

abstrakte Basisklasse:

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

} 

Umsetzung:

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

} 

Die folgende wirft die Ausnahme oben erwähnt:

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

Dies ist jedoch nicht werfen eine Ausnahme:

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

Wenn jemand Hilfe oder Anleitung anbieten kann, warum diese Ausnahme passiert, wäre ich sehr dankbar.

+0

möglich Duplikat von [$ Proxy25 kann nicht in meine Klasse Spring Framework umgewandelt werden] (http://stackoverflow.com/questions/5702364/proxy25-cannot-be-cast-to-my-class-spring-framework) – artbristol

Antwort

43

Spring verwendet JDK dynamic proxies standardmäßig ($Proxy58 ist einer von ihnen), die nur Proxy-Schnittstellen können. Dies bedeutet, dass der dynamisch erstellte Typ $Proxy58 eine oder mehrere der Schnittstellen implementiert, die von der Klasse "wrapped/target" (UserDao) implementiert wurden. Dies ist jedoch keine tatsächliche Unterklasse davon. Das ist im Grunde, warum Sie die userDao Bohne an die DaoSchnittstelle, aber nicht an die UserDaoKlasse werfen können.

Sie können <tx:annotation-driven proxy-target-class="true"/> verwenden, um Spring anzuweisen, CGLIB-Proxies zu verwenden, die tatsächliche Unterklassen der proxied-Klasse sind, aber ich denke, es ist besser, für Schnittstellen zu programmieren. Wenn Sie auf einige Methoden der proxied-Klasse zugreifen müssen, die nicht in einer ihrer Schnittstellen deklariert sind, sollten Sie sich zuerst fragen, warum dies der Fall ist?
(auch oben in Ihrem Code sind keine neue Methoden in UserDao eingeführt, so hat es keinen Sinn, die Bohne zu dieser konkreten Umsetzung Art ohnehin in Gießen.)

Sehen Sie mehr über verschiedene proxying Mechanismen in den offiziellen Spring reference.

+0

Sehr hilfreich für zukünftige Referenz. Danke @zagyi für die Einsicht! – mchandler

+1

Hilfreich für das Verständnis Guice auch. –

+6

"... Sie sollten sich zuerst fragen, warum das der Fall ist?" - Ein Beispiel ist das Testen interner Methoden in einem Komponententest. Ich möchte eine bestimmte Implementierung testen, nicht die Schnittstelle. Wie auch immer, gute Antwort! – Zeemee

4

Ich schrieb Komponententests und musste in der Lage sein, die DAOs für einige Anrufe auszugeben. Per dieser Jungs schreiben: http://www.techper.net/2009/06/05/how-to-acess-target-object-behind-a-spring-proxy/ Ich benutzte seine Methode zur Verfügung gestellt:

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

Dann können Sie es einfach mit dem Proxy aufrufen und das Objekt hinter dem Proxy bekommen und die Objekte darin direkt nach Bedarf manipulieren.

Verwandte Themen