【问题标题】:Spring / @Transactional with AspectJ is totally ignoredSpring / @Transactional 与 AspectJ 完全被忽略
【发布时间】:2013-03-25 13:54:13
【问题描述】:

我使用 Spring-Data Neo4j 2.2.0-RELEASE。 (我的以下问题适用于任何其他类型的实体映射,为什么不是 JPA)

在我的项目中,我有一个使用 @Transactional Spring 注释注释的公共方法,因为我想更新/保存其中的实体:

public class MeetingServices {

    private UserRepository userRepository;

    private MeetingRepository meetingRepository;

    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void setMeetingRepository(MeetingRepository meetingRepository) {
        this.meetingRepository = meetingRepository;
    }

    @Transactional("neo4jTransactionManager")
    public void save(Meeting meeting) {
        User creator = userRepository.getUserByEmail("test@test.com");
        creator.participateIn(meeting); // this line leads to a NotInTransactionException since it signals that no transaction context is associated.
        meeting.setCreator(creator);
    }

我的 application-context.xml 如下:

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

    <bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase">
        <constructor-arg value="target/neo4jgraph" />
    </bean>

    <neo4j:config graphDatabaseService="graphDatabaseService" />

    <bean id="meetingServices" class="services.MeetingServices">
        <property name="userRepository"><ref bean="userRepository"/></property>
        <property name="meetingRepository"><ref bean="meetingRepository"/></property>
    </bean>

    <bean id="userServices" class="services.UserServices">
        <property name="userRepository"><ref bean="userRepository"/></property>
    </bean>

    <bean id="neo4jTransactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager">
            <bean class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
                <constructor-arg ref="graphDatabaseService" />
            </bean>
        </property>
        <property name="userTransaction">
            <bean class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
                <constructor-arg ref="graphDatabaseService" />
            </bean>
        </property>
    </bean>

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

    <!-- auto-generated repositories for Neo4j storage -->
    <neo4j:repositories base-package="repositories"/> 

    <context:spring-configured/>

    <context:annotation-config/>

</beans>

正如我们在此配置中看到的,aspectJ 用于事务。

因此,我尝试通过将 application-context.xml 更改为使用 proxy 功能而不是 aspectJ 功能来测试另一种方法:

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

    <bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase">
        <constructor-arg value="target/neo4jgraph" />
    </bean>

    <neo4j:config graphDatabaseService="graphDatabaseService" />

    <bean id="meetingServices" class="services.MeetingServices">
        <property name="userRepository"><ref bean="userRepository"/></property>
        <property name="meetingRepository"><ref bean="meetingRepository"/></property>
    </bean>

    <bean id="userServices" class="services.UserServices">
        <property name="userRepository"><ref bean="userRepository"/></property>
    </bean>

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


    <neo4j:repositories base-package="repositories"/>

    <context:spring-configured/>

    <context:annotation-config/>

</beans>

此配置运行良好,因为 @Transactional(其 neo4jTransactionManager 参数当然已被删除)注释现在已考虑到我的服务方法。

我的问题是,(无论我的项目是否可以使用简单的proxy 方法):

在我的第一个 Spring 配置中,我遗漏了什么或配置错误导致 aspectJ 事务功能失败?

我目前正在使用 Spring 提高我的技术技能,并且阅读了几篇关于 aspectJ 的“加载时编织”的文章。这可能与我的问题有关吗?

【问题讨论】:

    标签: java spring aspectj spring-data spring-data-neo4j


    【解决方案1】:

    尝试添加 &lt;context:load-time-weaver/&gt; 以启用加载时编织并将 spring-aspects.jar 添加到类路径中。

    更多信息请见http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-aj-ltw-spring

    编辑

    对于通用java应用程序,即不在web或应用程序容器中运行,您需要通过javaagent选项启用java工具:

    java -javaagent:path/to/spring-instrument.jar your.Main
    

    如果你想编织你自己的切面,你需要提供一个带有切面声明的 META-INF/aop.xml 文件。 (仅 spring 方面不需要,它已在 spring-aspect.jar 中提供)。

    最后你可以改用编译时编织,例如using the maven aspectj plugin,:

    <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <configuration>
                    <complianceLevel>1.6</complianceLevel>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
    

    【讨论】:

    • 我已经尝试过了,但我最终得到了这个:Caused by: java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar
    • 添加主启动器的选项:java -javaagent:C:/projects/foo/lib/global/spring-instrument.jar foo.Main 参考示例
    • 我刚刚听从了你的建议 :) 但这导致了: 由:java.lang.VerifyError: (class: services/MeetingServices$$EnhancerByCGLIB$$73b088b5, method: setMeetingRepository signature: (Lrepositories/MeetingRepository;)V) Inconsistent stack height 1 != 0 引起。听起来像是一个已知的错误 (stackoverflow.com/questions/9027009/aspectj-verifyerror)。我使用 Java 7 .. 我刚刚尝试了建议:添加 -XX:-UseSplitVerifierto VM 选项但仍然出现错误。
    • 尝试使用 maven 并编译时编织。我只是发布一个例子。删除 ltw 标记和 javaagent 选项。使用编译时编织时不需要它们。
    • 谢谢,我一回到我的电脑就试试(maven方法),我会通知你的:)
    猜你喜欢
    • 1970-01-01
    • 2012-05-19
    • 2013-11-05
    • 2012-11-19
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    相关资源
    最近更新 更多