In meinem Projekt verwende ich derzeit AspectJ (nicht nur Spring AOP aufgrund einiger Einschränkungen) mit der Weberei zur Kompilierzeit. Um die Entwicklung auf Eclipse zu beschleunigen, möchte ich das Weben zur Ladezeit durchführen. Es gelingt mir, das zu tun, aber mit einer großen Einschränkung: eine Schnittstelle für meinen Dienst zu verwenden, die einige transaktionale Methoden enthielt. Wenn ich den Dienst mit seiner Implementierung anstelle seiner Schnittstelle deklariere, gibt es in der Aufruferklasse keine Weberei und daher wird keine Transaktion unterstützt.Wie konfiguriere ich AspectJ mit Ladezeit Weben ohne Schnittstelle
Also Wenn es von AspectJ unterstützt wird, wie AspectJ mit Load Time Weben ohne Schnittstelle zu konfigurieren?
habe ich ein kleines Projekt, das das Problem zu reproduzieren:
Der folgende Test nicht bestehen.
Der folgende Test erfolgreich sein, wenn:
der injizierte Dienst mit seiner Schnittstelle statt deren Umsetzung deklariert wird (dh ersetzen "@Inject MyServiceImpl Service" von "@Inject MyService Service"), gelingt es der Test .
Das Weben wird während der Kompilierung ausgeführt (die Konfiguration, POM & Feder Anwendungskontext, ist in diesem Fall offensichtlich anders). Aber mein Ziel ist es, das Weben zur Ladezeit durchzuführen, um jedes Mal, wenn ich eine Java-Datei speichere, eine Webphase zu vermeiden.
Spring AOP (tx: annotation-driven mode = "proxy"), das ist eine Proxy-basierte Lösung, wird anstelle von AspectJ verwendet. Aber in diesem Fall haben wir das Problem des Selbstaufrufs festgestellt, d. H. Eine Methode innerhalb des Zielobjekts, die eine andere Methode des Zielobjekts aufruft, führt nicht zur tatsächlichen Transaktion zur Laufzeit, selbst wenn die aufgerufene Methode mit @Transactional markiert ist.
aspectj-LTW/src/test/java/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/main/java/mycompany/aspectj_ltw/MyService.java
package mycompany.aspectj_ltw;
public interface MyService {
boolean isExecutedInTransaction();
}
aspectj-LTW/src/main/java/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/test/resources/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/test/resources/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>
VM Argumente den Test auszuführen:
-javaagent:C:/maven-2_local_repo/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar
Thank you! Ich denke, das ist eine ziemlich genaue Erklärung dessen, was vor sich geht.Ich bin nicht 100% sicher, denn nach dem, was ich gehört habe Spring zwei Klassenladegeräte und zwei Klassenladekarten - eine Testklasse und ihre Referenzen sollten zuerst in den ersten Lader geladen werden, Anmerkungen analysiert usw., aber dann werden sie verworfen und über AspectJ geladen zur Verfügung gestellt Lader, die das Weben tut ... Theoretisch sollte es Weben ermöglichen, richtig zu passieren, aber irgendwie tut es nicht. Ich werde versuchen, aspectjweaver javaagent und/oder reweavable Optionen hinzuzufügen, um zu sehen, ob es es behebt! – alexandroid
f *** ng .... brilliant. Ich habe gerade nach den frustrierendsten Stunden, die ich nach dem Ratnehmen habe, nach einiger Zeit den größten Atemzug genommen. Für die Aufzeichnung, einschließlich ein 'aspectjweaver' zusammen mit' feder-instrument' als javaagent ermöglichte mir, das Laden-Zeitweben richtig in einer Spring-Boot-Anwendung laufen zu lassen, einschließlich der Junit-Tests – drewmoore
@drewmoore Ich arbeite mit einem Spring-Boot mvc-Anwendung und muss eine Methode von einer anderen Methode innerhalb derselben Controller-Klasse aufrufen, wobei die letztere Methode mit '@ Async' versehen ist. Mir wurde gesagt, dass dies nicht möglich ist, wenn ich den "AspectJ-Proxy-Modus nicht aktiviere und einen Weber anbiete". Ist das ähnlich wie bei dir? –