Spring/@Transactional 与 AspectJ 完全被忽略

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

I use Spring-Data Neo4j 2.2.0-RELEASE. (my following issue would be applicable to any other kind of entity mapping, why not JPA)

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

In my project, I have a public method annotated with @Transactional Spring's annotation, since I want to update/save an entity inside it:

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 如下:

My application-context.xml is the following:

<?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 用于事务.

As we see in this configuration, aspectJ is used for transactions.

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

So, I tried to test another way of doing by changing my application-context.xml to use the proxy feature instead of aspectJ feature:

<?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 参数当然已删除)注释.

This configuration works pretty well since @Transactional (whose neo4jTransactionManager parameter was of course removed) annotation is now taken in account for my service's method.

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

My question is, (no matter whether my project would work with simple proxy method):

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

What did I miss or misconfigure in my first Spring's configuration that makes aspectJ transaction features failed?

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

I'm currently improving my technical skills with Spring, and read few articles about "Load-time weaving" for aspectJ. Might this be linked to my issue?

推荐答案

尝试添加 <context:load-time-weaver/> 以启用加载时间编织并添加 spring-aspects.jar 到类路径.

Try adding <context:load-time-weaver/> to enable load time weaving and add the spring-aspects.jar to the classpath.

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

编辑

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

For generic java applications, ie not running in a web or application container, you need to enable the java instrumentatioin via a javaagent option:

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

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

If you want to weaving your own aspects, you need to provide a META-INF/aop.xml file with aspect declarations. (Not requiered for spring only aspects, it's already provided on spring-aspect.jar).

最后你可以改用编译时编织,使用maven aspectj插件,例如:

Finally you can use compile time weaving instead, using the maven aspectj plugin, for example:

<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>

相关文章