Подтвердить что ты не робот

Прокси не может быть передан в класс

Я использую Spring для зависимостей подключений специально для классов DAO, которые используют Hibernate, но я получаю исключение, которое меня озадачивает:

$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" );

Если кто-либо может предложить какую-либо помощь или руководство относительно того, почему это исключение происходит, я был бы очень благодарен.

4b9b3361

Ответ 1

Spring по умолчанию использует JDK динамические прокси ($Proxy58 - один из них), который может использовать только прокси-интерфейсы. Это означает, что динамически созданный тип $Proxy58 будет реализовывать один или несколько интерфейсов, реализованных классом wrapped/target (UserDao), но он не будет фактическим подклассом. Именно поэтому вы можете использовать UserDao bean для интерфейса Dao, но не для класса UserDao.

Вы можете использовать <tx:annotation-driven proxy-target-class="true"/>, чтобы проинструктировать Spring использовать прокси CGLIB, которые являются фактическими подклассами класса proxied, но я считаю, что лучше использовать программу против интерфейсов. Если вам нужно получить доступ к некоторым методам из прокси-класса, которые не объявлены на одном из интерфейсов, вы должны сначала спросить себя, почему это так?
(Кроме того, в вашем коде выше нет новых методов, введенных в UserDao, поэтому нет никакого смысла лить bean для этого конкретного типа реализации).

Узнайте больше о различных механизмах проксирования в официальной Spring ссылке.

Ответ 2

Я писал модульные тесты и должен был иметь возможность заглушить 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
  }
}

Затем вы можете легко вызвать его с прокси-сервером и получить объект за прокси-сервером и напрямую манипулировать объектами в нем.