Comment configurer AspectJ avec des Temps de Chargement de Tissage sans Interface
Sur mon projet, j'utilise actuellement AspectJ (et pas seulement de Spring AOP en raison de certaines limitations) avec le tissage au Moment de la Compilation. Afin d'accélérer le développement sous Eclipse, je veux faire du tissage à l'Heure de la Charge. J'ai réussi à le faire mais avec une contrainte majeure: l'utilisation d'une interface pour mon service qui contenait les méthodes transactionnelles. Si je déclare le service de sa mise en œuvre à la place de son interface, en l'appelant la classe, il n'y a pas de tissage et donc pas de transaction pris en charge.
Donc si elle est prise en charge par AspectJ, comment configurer AspectJ avec des Temps de Chargement de Tissage sans Interface ?
J'ai créé un petit projet de reproduire le problème:
Le test suivant échouer.
Le test suivant réussir si :
- l'injection de service est déclarée avec son interface à la place de sa mise en œuvre (c'est à dire remplacer "@Inject MyServiceImpl service" par "@Inject MyService service"), le test de réussir.
- le tissage est exécuté lors de la compilation (la configuration, POM & Printemps contexte d'application, est évidemment différente dans ce cas). Mais mon but est de faire le tissage à la Charge à Temps pour éviter un tissage de phase à chaque fois que j'enregistre un fichier Java.
- Spring AOP (tx:annotation-driven mode="proxy"), qui est un proxy de la solution, est utilisé à la place d'AspectJ. Mais dans ce cas, nous avons rencontré les auto-invocation problème, c'est à dire une méthode de l'objet cible de l'appel à une autre méthode de l'objet cible, ne vous conduira pas à une transaction au moment de l'exécution, même si la méthode invoquée est marqué avec @Transactionnelle.
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 arguments pour exécuter le test:
-javaagent:C:/maven-2_local_repo/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar
OriginalL'auteur Thierry Abaléa | 2012-10-31
Vous devez vous connecter pour publier un commentaire.
Si je ne me trompe pas, la question ici n'est pas due à AspectJ, mais plutôt à la façon dont les choses fonctionnent dans la précision JUnit cas d'utilisation. Lors de l'exécution de votre test, le
MyServiceImplTest
classe est chargée en premier, avant que le Printemps est créé (vous avez besoin de la classe de test' annotations pour obtenir les runner et de configuration des lieux), donc avant toute Spring AOP mécanisme a été mis à profit. C'est, au moins, l'explication m'est venu quand j'ai fait face à la même situation, il y a quelques mois... Depuis le javaagent est-il de la JVM de démarrage, on pourrait avoir à lire/comprendre le tisserand de code pour expliquer pourquoi il ne parvient pas ici (je ne l'ai pas :p).De toute façon, le
MyServiceImplTest
type, avec tous ses membres, qui sont chargés avec des il - cela vaut pour les types de signatures de méthode en tant que bien, ne peut pas être tissé.Pour contourner ce problème:
ou ajouter le AspectJ tisserand à votre javaagents (en plus du printemps-instrument); avec cela, si je me souviens bien, le Printemps devrait être en mesure d'obtenir son AOP à base de mécanismes de travailler correctement:
-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
Nota: dans votre
META-INF/aop.xml
, il peut être nécessaire d'ajouter de la-Xreweavable
weaver option.f***ng.... brillant. j'ai juste pris le plus grand souffle, après le plus frustrant quelques heures, que j'ai depuis un certain temps après la prise de vos conseils. Pour le dossier, y compris un
aspectjweaver
avecspring-instrument
comme un javaagent m'a permis d'obtenir les temps de charge de tissage fonctionne correctement dans le printemps de démarrage de l'application, junit tests inclusJe suis en train de travailler avec une source de démarrage de l'application mvc et ont besoin d'invoquer une méthode à partir d'une autre méthode de la même classe de contrôleur, où cette dernière méthode est annoté avec
@Async
. On m'a dit que ce n'est pas possible, à moins que je activerAspectJ proxy mode and provide a weaver
. Est-ce similaire à ce que vous faites?Je suis l'aide de Printemps 4.2.6 et il semble que l'agent fournis par le printemps, aussi longtemps que le printemps liées à la configuration est tout à fait inutiles si vous utilisez l'agent fournis par AspectJ ... c'est tout ! Au moins, il a travaillé comme un charme pour moi (je suis aussi à l'aide de plusieurs classloading de gestion).
OriginalL'auteur Vincent
Tout d'abord , si vous utilisez maven, définissez votre pom.xml:
Puis vous avez eu pour compiler votre code en utilisant le compilateur aspectj.
Ce compilateur de générer un aop.xml fichier dans META-INF/aop.xml
(Je suis en utilisant eclipse sts)
Après cela, je veux exécuter un test Junit.
Donc, vous devez définir votre VM args dans l'eclipse exécuter fenêtre de configuration:
-javaagent:${ASPECTJ_WEAVER_1.7}\aspectjweaver-1.7.0.jar -javaagent:${SPRING_INSTRUMENT}\spring-instrument-3.1.2.RELEASE.jar
où ${ASPECTJ_WEAVER_1.7} ${SPRING_INSTRUMENT} sont un environtment var. L'utilisation de la var bouton pour créer ces vars (située en bas à droite de la fenêtre). Ces vars cible dans les dossiers où le aspectjweaver-1.7.0.jar et spring-instrument-3.1.2.RELEASE.jar sont situés. Suivez l'asistant de faire cela. Il n'est pas difficile.
Prendre soin que la précédente javaagent lignes n'ont pas l'invisible étrange personnage ou similaire. C'est étrange, mais j'ai dû le réécrire plusieurs fois la même ligne jusqu'à ce que l'éclipse a dit que cette ligne est fine.
Ensuite, vous pouvez lancer votre test Junit.
La première que vous pouvez voir est aspectj chargement à l'exécution. Plus tard, vous verrez printemps de chargement... et après que votre test sera exécuté est n'ai pas de printemps problème ou similaire.
C'est un processus lourd.
J'espère que cette information peut vous aider à
Ce qui concerne
OriginalL'auteur Antonio Martin