2013-04-16 14 views
21

Tôi đang sử dụng mùa xuân cho phụ thuộc hệ thống dây điện đặc biệt cho các lớp DAO sử dụng Hibernate, nhưng tôi nhận được một ngoại lệ mà đã cho tôi bối rối:Proxy không thể được đúc để CLASS

$ Proxy58 không thể được đúc để UserDao

My DAO được cấu hình như sau:

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

và tôi có một giao diện, lớp cơ sở trừu tượng và thực hiện cuối cùng như sau.

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

} 

Thực hiện:

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

} 

Sau đây ném ngoại lệ nêu trên:

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

này, tuy nhiên, không ném một ngoại lệ:

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

Nếu có ai có thể cung cấp bất kỳ trợ giúp hoặc hướng dẫn nào về lý do ngoại lệ này xảy ra, tôi sẽ rất đánh giá cao.

+0

bản sao có thể có của [$ Proxy25 không thể được truyền tới khung mùa xuân lớp học của tôi] (http://stackoverflow.com/questions/5702364/proxy25-cannot-be-cast-to-my-class-spring-framework) – artbristol

Trả lời

43

Sử dụng mùa xuân JDK dynamic proxies theo mặc định ($Proxy58 là một trong số chúng), chỉ có thể giao diện proxy. Điều này có nghĩa là kiểu được tạo động $Proxy58 sẽ thực hiện một hoặc nhiều giao diện được thực hiện bởi lớp được bao bọc/đích (UserDao), nhưng nó sẽ không phải là một lớp con thực sự của nó. Đó là lý do tại sao bạn có thể bỏ đậu userDao tới giao diện Dao, nhưng không phải là UserDaolớp.

Bạn có thể sử dụng <tx:annotation-driven proxy-target-class="true"/> để hướng dẫn Spring sử dụng proxy CGLIB là lớp con thực sự của lớp được ủy quyền, nhưng tôi nghĩ thực hành tốt hơn để lập trình chống lại giao diện. Nếu bạn cần truy cập một số phương thức từ lớp proxy không được khai báo trong một trong các giao diện của nó, bạn nên tự hỏi mình trước, tại sao lại là trường hợp này?
(Ngoài ra, trong mã của bạn ở trên không có phương pháp mới được giới thiệu trong UserDao, vì vậy không có điểm trong đúc đậu để loại thực hiện cụ thể này anyway.)

Xem thêm về cơ chế proxy khác nhau trong chính thức Spring reference.

+0

Cực kỳ hữu ích để tham khảo trong tương lai. Cảm ơn @zagyi cho cái nhìn sâu sắc! – mchandler

+1

Hữu ích cho sự hiểu biết Guice quá. –

+6

"... bạn nên tự hỏi mình trước, tại sao lại như vậy?" - một ví dụ là kiểm tra các phương thức nội bộ trong một thử nghiệm đơn vị. Tôi muốn thử nghiệm một triển khai cụ thể, không phải là giao diện. Dù sao, câu trả lời tuyệt vời! – Zeemee

4

Tôi đã viết các bài kiểm tra đơn vị và cần thiết để có thể phân tích các DAO cho một số cuộc gọi. mỗi chàng trai này gửi: http://www.techper.net/2009/06/05/how-to-acess-target-object-behind-a-spring-proxy/ tôi đã sử dụng phương pháp của ông cung cấp:

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

Sau đó, bạn có thể dễ dàng gọi nó với proxy và nhận được các đối tượng sau proxy và thao tác các đối tượng trong nó trực tiếp khi cần thiết.