Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring 如何在没有接口的情况下配置AspectJ和加载时编织_Spring_Aop_Aspectj_Spring Transactions_Load Time Weaving - Fatal编程技术网

Spring 如何在没有接口的情况下配置AspectJ和加载时编织

Spring 如何在没有接口的情况下配置AspectJ和加载时编织,spring,aop,aspectj,spring-transactions,load-time-weaving,Spring,Aop,Aspectj,Spring Transactions,Load Time Weaving,在我的项目中,我目前在编译时使用AspectJ(由于某些限制,不仅仅是SpringAOP)进行编织。为了加快Eclipse上的开发速度,我想在加载时进行编织。我成功地做到了这一点,但有一个主要的限制:为我的服务使用包含一些事务方法的接口如果我在caller类中声明服务及其实现而不是接口,则没有编织,因此不支持事务。 因此如果AspectJ支持它,那么如何配置AspectJ,使其具有无接口的加载时编织功能? 我创建了一个复制该问题的小项目: 以下测试失败 以下测试在以下情况下成功: 注入的服务是

在我的项目中,我目前在编译时使用AspectJ(由于某些限制,不仅仅是SpringAOP)进行编织。为了加快Eclipse上的开发速度,我想在加载时进行编织。我成功地做到了这一点,但有一个主要的限制:为我的服务使用包含一些事务方法的接口如果我在caller类中声明服务及其实现而不是接口,则没有编织,因此不支持事务。

因此如果AspectJ支持它,那么如何配置AspectJ,使其具有无接口的加载时编织功能?

我创建了一个复制该问题的小项目:

以下测试失败

以下测试在以下情况下成功:

  • 注入的服务是用接口声明的,而不是它的实现(即用“@Inject MyService service”替换“@Inject MyService impl service”),测试成功

  • 编织是在编译过程中执行的(在本例中,配置POM和Spring应用程序上下文明显不同)。但我的目标是在加载时进行编织,以避免每次保存Java文件时出现编织阶段

  • SpringAOP(tx:annotation-driven-mode=“proxy”)是一种基于代理的解决方案,用于替代AspectJ。但在本例中,我们遇到了自调用问题,即目标对象内的方法调用目标对象的其他方法,即使调用的方法标记为@Transactional,也不会在运行时导致实际事务

aspectj ltw/src/test/java/mycompany/aspectj_ltw/myserviceinmpltest.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/myserviceinpl.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,而是因为JUnit用例中的工作方式。在运行测试时,首先加载
MyServiceImplTest
类,然后创建Spring上下文(您需要测试类的注释来获取适当的运行程序和配置位置),因此在使用任何Spring AOP机制之前。这是,至少,我在几个月前面对同样情况时提出的解释。。。由于javaagent从JVM启动时就在那里,因此必须完全阅读/理解weaver的代码,才能准确地解释它在这里失败的原因(我没有:p)

因此无论如何,
MyServiceImplTest
类型及其加载的所有成员类型(也适用于方法签名中的类型)都无法编织

要解决此问题,请执行以下操作:

  • 或者避免在测试类成员和方法签名中使用编织类型(例如,像您那样使用接口)
  • 或者将AspectJ weaver添加到JavaAgent中(除了spring instrument 1);如果我没记错的话,Spring应该能够使其基于AOP的机制正常工作:

    -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
weaver选项。

首先,如果您使用的是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>

org.springframework
弹簧乐器
3.1.2.1发布
org.aspectj
aspectjweaver
1.7
然后必须使用aspectj编译器编译代码。 此编译器在META-INF/aop.xml中生成一个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>
(我正在使用eclipse sts) 之后,我想运行一个Junit测试。 因此,您必须在eclipse运行配置窗口中设置VM参数: -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按钮创建这些变量(位于窗口的右下角)。这些变量指向aspectjweaver-1.7.0.jar和spring-instrument-3.1.2.RELEASE.jar所在的文件夹。跟随助手做这个。这并不难。 注意前面的javaagent行中没有任何不可见的奇怪字符或类似字符。这听起来很奇怪,但我不得不重写同一行好几次,直到eclipse说这行很好

然后,您可以运行Junit测试。 首先可以看到aspectj运行时加载。稍后您将看到弹簧加载。。。之后,您的测试将运行,因为它没有任何spring问题或类似问题。 这是一个沉重的过程

我希望这些信息能对你有所帮助


问候

谢谢!我认为这是对发生的事情的非常接近的解释。我不是100%确定,因为据我所知,Spring使用了2个类加载程序和2个类加载通过-一个测试类及其引用应该首先加载到第1个加载程序中,分析注释等,但随后它们被丢弃,并通过AspectJ提供的加载程序加载,该加载程序进行编织。。。从理论上讲,它应该允许织布正确地进行,但不知何故它并没有。我将尝试添加AspectJweaverJavaAgent和/或可重写选项,看看它是否修复了它!f***ng。。。。明亮的在经历了最令人沮丧的几个小时之后,在接受了你的建议之后,我刚刚深吸了一口气。作为记录,包括
aspectjweaver
以及
spring工具
作为javaagent使我能够在spring引导应用程序中正确运行加载时编织,junit测试included@drewmoore我正在使用spring boot mvc应用程序,需要调用一个
-javaagent:C:/maven-2_local_repo/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar
    <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>