2012-10-31 46 views
13

के बिना लोड टाइम बुनाई के साथ AspectJ को कॉन्फ़िगर कैसे करें मेरे प्रोजेक्ट पर, मैं वर्तमान में संकलन समय पर बुनाई के साथ AspectJ (केवल कुछ सीमा के कारण वसंत एओपी नहीं) का उपयोग करता हूं। ग्रहण पर विकास को तेज करने के लिए, मैं लोड समय पर बुनाई करना चाहता हूं। मैं ऐसा करने में सफल हूं लेकिन एक प्रमुख बाधा के साथ: मेरी सेवा के लिए एक इंटरफेस का उपयोग जिसमें कुछ लेनदेन संबंधी विधियां थीं। यदि मैं कॉलर क्लास में अपने इंटरफ़ेस की बजाय इसके कार्यान्वयन के साथ सेवा घोषित करता हूं, तो कोई बुनाई नहीं होती है और इसलिए कोई लेनदेन समर्थित नहीं होता है।इंटरफेस

तो यदि यह AspectJ द्वारा समर्थित है, तो इंटरफेस के बिना लोड टाइम बुनाई के साथ AspectJ को कॉन्फ़िगर कैसे करें?

निम्नलिखित परीक्षण असफल:

मैं एक छोटे से परियोजना है कि इस मुद्दे को दोबारा बनाया।

निम्न परीक्षण सफल होने अगर:

  • इंजेक्शन सेवा इसके कार्यान्वयन के बजाय इसके इंटरफेस के साथ घोषित किया जाता है (यानी "@Inject MyServiceImpl सेवा" द्वारा "@Inject MyService सेवा" की जगह), परीक्षण सफल होने के ।

  • बुनाई संकलन के दौरान निष्पादित किया जाता है (कॉन्फ़िगरेशन, पीओएम & वसंत अनुप्रयोग संदर्भ, इस मामले में स्पष्ट रूप से अलग है)। लेकिन मेरा लक्ष्य है कि जब भी मैं जावा फ़ाइल को सहेजता हूं, तो बुनाई चरण से बचने के लिए लोड-टाइम पर बुनाई करना होता है।

  • वसंत एओपी (टीएक्स: एनोटेशन-संचालित मोड = "प्रॉक्सी"), जो प्रॉक्सी-आधारित समाधान है, का उपयोग AspectJ के बजाय किया जाता है। लेकिन इस मामले में, हमें स्वयं-आमंत्रण समस्या का सामना करना पड़ा, यानि लक्ष्य वस्तु के भीतर किसी अन्य विधि को लक्षित करने वाले लक्ष्य ऑब्जेक्ट के भीतर एक विधि, रनटाइम पर वास्तविक लेनदेन का कारण नहीं बनती है, भले ही चालान विधि @ ट्रान्सएक्शनल के साथ चिह्नित हो।

AspectJ-LTW/src/परीक्षण/जावा/mycompany/aspectj_ltw/MyServiceImplTest.java

package mycompany.aspectj_ltw; 

import static junit.framework.Assert.assertTrue; 

import javax.inject.Inject; 

import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.test.context.ContextConfiguration; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "classpath:/META-INF/spring/applicationContext.xml" }) 
public class MyServiceImplTest { 

    @Inject 
    MyServiceImpl service; 

    @Test 
    public void shouldBeExecutedInTransaction() { 
     assertTrue(this.service.isExecutedInTransaction()); 
    } 
} 

AspectJ-LTW/src/मुख्य/जावा/mycompany/aspectj_ltw/MyService.java

package mycompany.aspectj_ltw; 

public interface MyService { 

    boolean isExecutedInTransaction(); 

} 

AspectJ-LTW/src/मुख्य/जावा/mycompany/aspectj_ltw/MyServiceImpl.java

package mycompany.aspectj_ltw; 

import org.springframework.stereotype.Service; 
import org.springframework.transaction.annotation.Transactional; 
import org.springframework.transaction.support.TransactionSynchronizationManager; 

@Service 
public class MyServiceImpl implements MyService { 

    @Transactional 
    public boolean isExecutedInTransaction() { 
     return TransactionSynchronizationManager.isActualTransactionActive(); 
    } 

} 

AspectJ-LTW/src/परीक्षण/संसाधन/META-INF/applicationContext.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> 

    <context:component-scan base-package="mycompany.aspectj_ltw" /> 

    <context:load-time-weaver aspectj-weaving="on" /> 
    <aop:config proxy-target-class="true"/> 
    <aop:aspectj-autoproxy proxy-target-class="true"/> 
    <tx:annotation-driven mode="aspectj" 
     transaction-manager="transactionManager" proxy-target-class="true" /> 

    <bean class="org.apache.commons.dbcp.BasicDataSource" 
     destroy-method="close" id="dataSource"> 
     <property name="driverClassName" value="org.h2.Driver" /> 
     <property name="url" value="jdbc:h2:mem:mydb" /> 
     <property name="username" value="sa" /> 
     <property name="password" value="" /> 
    </bean> 
    <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" 
     id="transactionManager"> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 
</beans> 

AspectJ-LTW/src/परीक्षण/संसाधन/META-INF/aop.xml

<!DOCTYPE aspectj PUBLIC 
     "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> 
<aspectj> 
    <weaver options="-showWeaveInfo -debug -verbose -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler"> 
     <include within="mycompany.aspectj_ltw..*"/> 
    </weaver> 
</aspectj> 

AspectJ-LTW \ pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 

    <groupId>mycompany</groupId> 
    <artifactId>aspectj-ltw</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <packaging>jar</packaging> 
    <name>aspectj-ltw</name> 

    <properties> 
     <spring.version>3.0.5.RELEASE</spring.version> 
    </properties> 

    <dependencies> 
     <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>4.8.2</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-core</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-test</artifactId> 
      <version>${spring.version}</version> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-aop</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-aspects</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-tx</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>org.aspectj</groupId> 
      <artifactId>aspectjrt</artifactId> 
      <version>1.7.0</version> 
     </dependency> 
     <dependency> 
      <groupId>org.aspectj</groupId> 
      <artifactId>aspectjweaver</artifactId> 
      <version>1.7.0</version> 
     </dependency> 
     <dependency> 
      <groupId>javax.inject</groupId> 
      <artifactId>javax.inject</artifactId> 
      <version>1</version> 
     </dependency> 
     <dependency> 
      <groupId>cglib</groupId> 
      <artifactId>cglib-nodep</artifactId> 
      <version>2.2</version> 
     </dependency> 
     <dependency> 
      <groupId>commons-dbcp</groupId> 
      <artifactId>commons-dbcp</artifactId> 
      <version>1.4</version> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-jdbc</artifactId> 
      <version>${spring.version}</version> 
     </dependency> 
     <dependency> 
      <groupId>com.h2database</groupId> 
      <artifactId>h2</artifactId> 
      <version>1.2.143</version> 
     </dependency> 
     <dependency> 
      <groupId>ch.qos.logback</groupId> 
      <artifactId>logback-core</artifactId> 
      <version>0.9.24</version> 
     </dependency> 
     <dependency> 
      <groupId>ch.qos.logback</groupId> 
      <artifactId>logback-classic</artifactId> 
      <version>0.9.24</version> 
     </dependency> 
     <dependency> 
      <groupId>org.slf4j</groupId> 
      <artifactId>log4j-over-slf4j</artifactId> 
      <version>1.6.1</version> 
     </dependency> 
    </dependencies> 
    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-surefire-plugin</artifactId> 
       <configuration> 
        <forkMode>always</forkMode> 
        <argLine> 
         -javaagent:C:/maven-2_local_repo/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar 
        </argLine> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 
</project> 

वीएम तर्क परीक्षण चलाने के लिए:

-javaagent:C:/maven-2_local_repo/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar 

उत्तर

14

यदि मुझे गलत नहीं लगता है, तो यहां समस्या AspectJ के कारण नहीं है, बल्कि जिस तरह से चीजें सटीक जुनीट उपयोग मामले में काम करती हैं।अपना परीक्षण चलाते समय, MyServiceImplTest कक्षा वसंत संदर्भ बनने से पहले पहले लोड की जाती है (आपको उपयुक्त धावक और कॉन्फ़िगरेशन स्थान प्राप्त करने के लिए टेस्ट क्लास की टिप्पणियों की आवश्यकता होती है), इसलिए किसी भी वसंत एओपी तंत्र का लाभ उठाने से पहले। कम से कम, कुछ महीनों पहले जब मुझे उसी स्थिति का सामना करना पड़ा था, तब से स्पष्टीकरण आया था ... चूंकि जावामैंट जेवीएम स्टार्टअप से है, इसलिए किसी को भी वीवर के कोड को ठीक से पढ़ना/समझना होगा समझाओ कि यह यहां क्यों विफल रहता है (मैंने नहीं किया: पी)।

तो वैसे भी, MyServiceImplTest प्रकार, इसके सभी सदस्यों के प्रकारों के साथ, जो इसके साथ लोड होते हैं - यह विधि हस्ताक्षरों में भी प्रकार के लिए जाता है - बुना नहीं जा सकता है।

इस हल करने के लिए:

  • या तो (इंटरफेस जैसे का उपयोग कर की तरह तुमने किया था)
  • परीक्षण वर्ग के सदस्यों और तरीकों हस्ताक्षर में बुना प्रकार का उपयोग कर से बचने या अपने javaagents को बुनकर AspectJ जोड़ने (वसंत-उपकरण के अलावा एक); इसके साथ, अगर मुझे सही ढंग से याद किया जाता है, तो वसंत अपने एओपी-आधारित तंत्र को ठीक से काम करने में सक्षम होना चाहिए:

    -javaagent: /maven-2_local_repo/org/aspectj/aspectjweaver/1.7.0/aspectjweaver-1.7.0 .jar -javaagent: /maven-2_local_repo/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar

नोटा: अपने META-INF/aop.xml में, यह हो सकता है -Xreweavable वीवर विकल्प जोड़ने के लिए आवश्यक हो।

+0

धन्यवाद मदद कर सकते हैं! मुझे लगता है कि यह क्या हो रहा है के बारे में बहुत करीब है।मैं 100% निश्चित नहीं हूं क्योंकि मैंने जो सुना है, उससे वसंत 2 वर्ग लोडर और 2 वर्ग लोड पास का उपयोग करता है - एक टेस्ट क्लास और इसके संदर्भों को सबसे पहले लोडर, एनोटेशन विश्लेषण आदि में लोड किया जाना चाहिए, लेकिन फिर उन्हें छोड़ दिया जाता है और AspectJ के माध्यम से लोड किया जा रहा है प्रदान किया गया लोडर जो बुनाई करता है ... सिद्धांत रूप में इसे बुनाई ठीक से होने की अनुमति देनी चाहिए लेकिन किसी भी तरह से यह नहीं करता है। मैं यह देखने के लिए aspectfweaver javaagent और/या reweavable विकल्पों को जोड़ने का प्रयास करूंगा कि यह ठीक करता है या नहीं! – alexandroid

+3

एफ *** एनजी .... शानदार। मैंने सबसे निराशाजनक कुछ घंटों के बाद सबसे बड़ी सांस ली, कि मेरी सलाह लेने के बाद मुझे थोड़ी देर में है। रिकार्ड के लिए, 'स्प्रिंग-वाद्य यंत्र' के साथ एक 'पहलू-उपकरण' के साथ एक जावावेन्ट के रूप में मुझे वसंत-बूट अनुप्रयोग में लोड-टाइम बुनाई ठीक से चलने में सक्षम बनाता है, जूनिट परीक्षणों में – drewmoore

+0

@ ड्रूमोरोर मैं वसंत-बूट के साथ काम कर रहा हूं एमवीसी अनुप्रयोग और एक ही विधि को उसी नियंत्रक वर्ग के भीतर एक विधि से बुलाए जाने की आवश्यकता है, जहां बाद की विधि '@ Async' के साथ एनोटेट की गई है। मुझे बताया गया कि यह तब तक संभव नहीं है जब तक कि मैं 'AspectJ प्रॉक्सी मोड सक्षम नहीं करता और एक वीवर प्रदान करता हूं'। क्या यह वही है जो आप कर रहे हैं? –

0

सबसे पहले, यदि आप Maven का उपयोग कर रहे हैं, अपने pom.xml सेट:

<dependency> 
     <groupId>org.springframework</groupId> 
     <artifactId>spring-instrument</artifactId> 
     <version>3.1.2.RELEASE</version> 
    </dependency> 
    <dependency> 
     <groupId>org.aspectj</groupId> 
     <artifactId>aspectjweaver</artifactId> 
     <version>1.7</version> 
    </dependency> 

तो फिर आप अपने कोड AspectJ संकलक का उपयोग कर संकलित करने के लिए किया है। इस संकलक META-INF/aop.xml

में एक aop.xml फ़ाइल (मैं ग्रहण sts उपयोग कर रहा हूँ) उसके बाद उत्पन्न, मैं एक JUnit परीक्षण चलाना चाहते हैं। तो आपको ग्रहण रन कॉन्फ़िगरेशन विंडो में अपने वीएम तर्क सेट करना होगा: -javaagent: $ {ASPECTJ_WEAVER_1.7} \ aspectjweaver-1.7.0.jar -javaagent: $ {SPRING_INSTRUMENT} \ spring-instrument-3.1.2। RELEASE.jar

जहां $ {ASPECTJ_WEAVER_1.7} $ {SPRING_INSTRUMENT} एक परिवेश var है। इन वर्रों को बनाने के लिए var बटन का उपयोग करें (विंडो के निचले दाएं भाग में स्थित है)। ये वर्ण फ़ोल्डर्स को लक्षित करते हैं जहां पहलूवेवर-1.7.0.jar और वसंत-उपकरण-3.1.2.RELEASE.jar स्थित हैं। इसे बनाने के लिए सहायक का पालन करें। यह कठिन नहीं है। ध्यान रखें कि पिछले जावागेंट लाइनों में कोई अदृश्य अजीब चरित्र या समान नहीं है। यह अजीब बात है लेकिन मुझे ग्रहण करने तक कई बार एक ही पंक्ति को फिर से लिखना पड़ा जब तक कि यह पंक्ति ठीक नहीं है।

फिर, आप अपना जुनीट परीक्षण चला सकते हैं। सबसे पहले आप देख सकते हैं पहलू रनटाइम लोडिंग। बाद में आप वसंत लोडिंग देखेंगे ... और उसके बाद आपका परीक्षण चलने वाला कोई वसंत समस्या या समान नहीं है। यह एक भारी प्रक्रिया है।

मुझे आशा है कि इस जानकारी को आप

सादर