2010-08-06 22 views
67

मैं वसंत लेनदेन के लिए नया हूँ। कुछ चीज जो मैंने वास्तव में अजीब पाया, शायद मैं इसे ठीक से समझ गया था। मैं विधि स्तर के चारों ओर एक लेनदेन करना चाहता था और मेरे पास एक ही कक्षा के भीतर एक कॉलर विधि है और ऐसा लगता है कि इसे पसंद नहीं है, इसे अलग वर्ग से बुलाया जाना है। मुझे समझ में नहीं आता कि यह कैसे संभव है। अगर किसी को इस मुद्दे को हल करने का विचार है, तो मैं बहुत सराहना करता हूं। मैं एनोटेटेड लेनदेन विधि को कॉल करने के लिए एक ही कक्षा का उपयोग करना चाहता हूं।स्प्रिंग @ ट्रांज़ेक्शन विधि उसी वर्ग के भीतर विधि द्वारा कॉल करती है, काम नहीं करती है?

public class UserService { 

    @Transactional 
    public boolean addUser(String userName, String password) { 
     try { 
      // call DAO layer and adds to database. 
     } catch (Throwable e) { 
      TransactionAspectSupport.currentTransactionStatus() 
        .setRollbackOnly(); 

     } 
    } 

    public boolean addUsers(List<User> users) { 
     for (User user : users) { 
      addUser(user.getUserName, user.getPassword); 
     } 
    } 
} 

उत्तर

70

यह वसंत AOP के साथ एक सीमा है:

यहाँ कोड है। (गतिशील वस्तुओं और CGLIB)

यदि आप लेनदेन को संभालने के लिए वसंत को AspectJ का उपयोग करने के लिए कॉन्फ़िगर करते हैं, तो आपका कोड काम करेगा।

सरल और शायद सबसे अच्छा विकल्प आपके कोड को दोबारा करने का है। उदाहरण के लिए एक वर्ग जो उपयोगकर्ताओं को नियंत्रित करता है और एक जो प्रत्येक उपयोगकर्ता को संसाधित करता है। फिर वसंत एओपी के साथ डिफ़ॉल्ट लेनदेन हैंडलिंग काम करेगा।

AspectJ के साथ लेनदेन से निपटने

लेनदेन के लिए AspectJ उपयोग करने के लिए सक्षम करने के लिए वसंत के लिए विन्यास टिप्स, आप AspectJ के लिए मोड सेट करना होगा:

<tx:annotation-driven mode="aspectj"/> 

आप एक पुराने के साथ स्प्रिंग उपयोग कर रहे हैं 3.0 से संस्करण, आप भी अपने स्प्रिंग विन्यास को यह जोड़ना होगा:

<bean class="org.springframework.transaction.aspectj 
     .AnnotationTransactionAspect" factory-method="aspectOf"> 
    <property name="transactionManager" ref="transactionManager" /> 
</bean> 
+0

जानकारी के लिए धन्यवाद। मैंने अभी कोड को दोहराया है, लेकिन क्या आप मुझे AspectJ का उपयोग करके एक उदाहरण भेज सकते हैं या मुझे कुछ उपयोगी लिंक प्रदान कर सकते हैं। अग्रिम में धन्यवाद। माइक। – Mike

+0

मेरे उत्तर में लेनदेन विशिष्ट AspectJ विन्यास जोड़ा गया। मुझे उम्मीद है यह मदद करेगा। – Espen

+1

आपकी सभी मदद के लिए धन्यवाद। यह काम करता हैं!! – Mike

42

समस्या यहाँ है , कि वसंत के एओपी प्रॉक्सी का विस्तार नहीं होता है बल्कि कॉल को अवरुद्ध करने के लिए आपके सेवा उदाहरण को लपेटता है। इसका प्रभाव यह है कि, आपके सेवा उदाहरण के भीतर से "यह" किसी भी कॉल को सीधे उस उदाहरण पर बुलाया जाता है और रैपिंग प्रॉक्सी द्वारा अवरुद्ध नहीं किया जा सकता है (प्रॉक्सी किसी भी कॉल के बारे में भी अवगत नहीं है)। एक समाधान पहले से ही उल्लेख किया गया है। एक और निफ्टी सिर्फ स्प्रिंग को सेवा में सेवा का एक उदाहरण इंजेक्ट करना होगा, और इंजेक्शन उदाहरण पर अपनी विधि को कॉल करना होगा, जो आपके लेनदेन को संभालने वाली प्रॉक्सी होगी। लेकिन बारे में पता होना, यह बुरा दुष्प्रभाव भी हो सकता है, अगर आपकी सेवा सेम एक सिंगलटन नहीं है:

<bean id="userService" class="your.package.UserService"> 
    <property name="self" ref="userService" /> 
    ... 
</bean> 

public class UserService { 
    private UserService self; 

    public void setSelf(UserService self) { 
     this.self = self; 
    } 

    @Transactional 
    public boolean addUser(String userName, String password) { 
     try { 
     // call DAO layer and adds to database. 
     } catch (Throwable e) { 
      TransactionAspectSupport.currentTransactionStatus() 
       .setRollbackOnly(); 

     } 
    } 

    public boolean addUsers(List<User> users) { 
     for (User user : users) { 
      self.addUser(user.getUserName, user.getPassword); 
     } 
    } 
} 
+2

) के लिए काम नहीं करता है यदि आप इस मार्ग पर जाने का विकल्प चुनते हैं (चाहे यह अच्छा डिजाइन है या नहीं, तो कोई अन्य मामला है) और कन्स्ट्रक्टर इंजेक्शन का उपयोग न करें, सुनिश्चित करें कि आप यह भी देखें [यह प्रश्न] (http://stackoverflow.com/questions/5152686/self-injection-with-spring) – Jeshurun

0

आप एक ही कक्षा के अंदर BeanFactory autowired और क्या कर सकते हैं एक

getBean(YourClazz.class)

यह स्वचालित रूप से आपकी कक्षा को प्रॉक्सी कर देगा और आपके @ ट्रांसेक्शन या अन्य एओपी एनोटेशन को ध्यान में रखेगा।

+2

इसे एक बुरी आदत के रूप में माना जाता है। यहां तक ​​कि बीन को बार-बार इंजेक्शन देना बेहतर होता है। GetBean (Clazz) का उपयोग करना एक तंग है अपने कोड के अंदर वसंत एप्लिकेशनकॉन्टेक्स्ट कक्षाओं पर युग्मन और मजबूत निर्भरता। कक्षा द्वारा बीन प्राप्त करने से वसंत लपेटने के मामले में काम नहीं हो सकता है (वर्ग बदला जा सकता है)। –

5

यह स्वयं आमंत्रण के लिए मेरा समाधान है।

private SBMWSBL self; 
@Autowired private ApplicationContext applicationContext; 

@PostConstruct 
public void postContruct(){ 
    self =applicationContext.getBean(SBMWSBL.class); 
} 
संबंधित मुद्दे