2010-10-04 12 views
9

मैं जानता हूँ कि यह बहुत बार पूछा जाता है, लेकिन मैं एक काम समाधान नहीं मिल सकता है:सार डीएओ पैटर्न और वसंत की "प्रॉक्सी को नहीं डाला जा सकता ..." समस्या!

यह मेरा AbstractDAO है:

public interface AbstractDao<T> 
{ 
    public T get(Serializable id); 
    //other CRUD operations 
} 

और ये मेरे जेपीए का क्रियान्वयन है:

public abstract class AbstractDaoJpaImpl<T> implements AbstractDao<T> , Serializable 
{ 
    protected EntityManager em; 

    protected Class<T> clazz; 

    @SuppressWarnings("unchecked") 
    public AbstractDaoJpaImpl() 
    { 
    ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass(); 
    this.clazz = (Class<T>) genericSuperclass.getActualTypeArguments()[0]; 
    } 

    public abstract void setEntityManager(EntityManager em); 
    //implementations skipped 
} 

और यह एक इकाई का दाओ है:

public interface PersonDao extends AbstractDao<Person> 
{ 
    //empty 
} 

यहां

@Repository 
public class PersonDaoImpl extends AbstractDaoJpaImpl<Person> implements PersonDao , OtherInterface 
{ 
    @PersistenceContext(unitName="company") 
    @Override 
    public void setEntityManager(EntityManager em) 
    { 
    this.em = em; 
    } 

    @Override // implements OtherInterface.additionalMethods() 
    public additionalMethods() 
    { 
    // implements... 
    } 
} 

पूरे वास्तुकला सरल है::

इंटरफ़ेस AbstractDao को परिभाषित करता है सरल CRUD तरीकों इसके कार्यान्वयन है।

इंटरफ़ेस पर्सनडाओ किसी भी एडन विधियों के बिना सारडाडो को बढ़ाता है।

वर्ग AbstractDaoJpaImpl) AbstractDao

की जेपीए के कार्यान्वयन

वर्ग PersonDaoImpl AbstractDaoJpaImpl प्रदान करता है और PersonDao और OtherInterface लागू करता है, जो aditionalMethods कहते हैं ( ...

यदि परिभाषित करता है, PersonDaoImpl केवल लागू करता PersonDao, अन्य इंटरफेस लागू करने के बिना .additionalMethods(), सबकुछ ठीक काम करता है।

मैं अपने वसंत के एक्सएमएल फ़ाइल में

<tx:annotation-driven transaction-manager="transactionManager" /> 

उपयोग कर सकते हैं।

लेकिन, PersonDaoImpl लागू करता OtherInterface (s), जब परीक्षण/चल रहा है, मैं डीएओ, जैसे PersonDaoImpl या OtherInterfaces को PersonDao से कास्ट करने के लिए है :

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations={"classpath:app.xml"}) 
@TransactionConfiguration(transactionManager="transactionManager" , defaultRollback=false) 
public class PersonDaoTest 
{ 
    @Inject 
    PersonDao dao; 

    @Test 
    public void testAdditionalMethod() 
    { 
    PersonDaoImpl impl = (PersonDaoImpl) dao; 
    System.out.println(impl.additionalMethod(...)); 
    } 
} 

समस्या तब होती है जब (PersonDaoImpl) dao, जो थ्रो "प्रॉक्सी PersonDaoImpl में ढाला नहीं जा सकता" अपवाद:

java.lang.ClassCastException: $Proxy36 cannot be cast to foobar.PersonDaoImpl 
    at foobar.PersonDaoTest.testAdditionalMethod(PersonDaoTest.java:36) 

इस बार पूछा जाता है जब googleing, हर कोईको proxy-target-class="true" जोड़ने का सुझाव:

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" /> 

यह जेडीके की गतिशील प्रॉक्सी के बजाय CGLIB का उपयोग करेगा।

लेकिन यह एक और अपवाद फेंकता है जब वसंत आरंभ: AbstractDaoJpaImpl के निर्माता में

Caused by: java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType 

:

ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass(); 

हर सवाल यहाँ बंद हो जाता है, मैं किसी भी काम कर समाधान अब नहीं मिल रहा।

क्या कोई मुझे एक कामकाजी समाधान दे सकता है? बहुत बहुत धन्यवाद!

पर्यावरण: वसंत-3.0.4, javaee-api-6.0, javax.inject, cglib-2.2, हाइबरनेट-जेपीए-2.0-api-1.0.0,

उत्तर

12

आप गलत समस्या को हल करने जा रहे हैं। प्रॉक्सिड बीन्स मूल वर्गों, एक तरफ या दूसरे को डालने के लिए नहीं हैं। यह निर्भरता इंजेक्शन के पूरे बिंदु को तोड़ देगा। आखिरकार: जब आप एक इंटरफेस के रूप में निर्भरता निर्दिष्ट करते हैं तो आप एक बीन का अनुरोध कर रहे हैं जो अनुबंध पूरा करता है, लेकिन कार्यान्वयन विवरण नहीं। इसे मूल बीन कक्षा में कास्ट करना इस ढीले युग्मन को तोड़ देता है।

आप कह रहे हैं कि OtherInterface पर कॉल करने वाले इंटरफ़ेस द्वारा अतिरिक्त विधियों का बैक अप लिया गया है, तो इसका उपयोग क्यों न करें? आखिरकार, प्रॉक्सी सभी लक्षित वर्ग 'इंटरफेस को लागू नहीं करेगा, न केवल इंजेक्शन वाले।

  1. अलग अपनी चिंताओं और विभिन्न इंटरफेस के लिए अलग सेम का उपयोग
  2. एक मेटा-इंटरफेस कि OtherInterface फैली बनाएँ:

    @Test 
    public void testAdditionalMethod() 
    { 
        OtherInterface oi = (OtherInterface) dao; 
        System.out.println(oi.additionalMethod(...)); 
    } 
    

    मूल रूप से आप इन विकल्पों (स्वच्छ से गंदा करने के लिए क्रमबद्ध) है और PersonDao और अपने बीन को लागू करें कि metainterface

  3. बीन को इंटरफ़ेस पर किसी भी क्षण की आवश्यकता है।
+0

धन्यवाद, मुझे अन्य इंटरफेस अन्य इंटरफेसइंपल इंजेक्ट करना चाहिए; और अन्यInterfaceImpl के खिलाफ परीक्षण। यह काम करता हैं ! – smallufo

0

हाँ वसंत हमेशा प्रॉक्सी वर्गों बनाता है और thats कैसे यह वास्तव में गैर दखल बुनाई और xml config द्वारा aop की खोज की ... वहाँ के नियमों का पालन करने के लिए और काम arounds हो shud वसंत दस्तावेज में कहा कि त्रुटि के लिए googling कोशिश।

संबंधित मुद्दे