Spring 方面由 AspectJ 编译器编织,可在 Maven 中工作,但不能在 IntelliJ IDEA 中工作

标签 spring intellij-idea aspectj lombok aspectj-maven-plugin

我正在使用 Spring boot 2.5.5 和 AspectJ 1.9.7 (CTW)。我发现有时事务不会回滚,要解决这个问题,我只需要重新编译代码并再次运行它。例如:

我有方法 addB() 持久化实体 B,方法 addC() 抛出异常,方法 A() 将它们组合起来。当我调用 A() 时,抛出异常,但实体 B 保留在数据库中(如预期)。当我用 @Transactional 注释方法 A() 时,结果是相同的。但是,如果我再次构建所有内容(没有任何更改),那么事务将被回滚,并且数据库中没有新记录。

这是我的完整 POM:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.abcc</groupId>
    <artifactId>abcc</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>abcc</name>
    <description>abcc</description>
    <properties>
        <java.version>11</java.version>
        <log4j2.version>2.15.0</log4j2.version>
        <aspectj.version>1.9.7</aspectj.version>
        <aspectj-maven-plugin.version>1.14.0</aspectj-maven-plugin.version>
    </properties>
    <dependencies>
        <!--SPRING-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!--CACHE-->
        <dependency>
            <groupId>javax.cache</groupId>
            <artifactId>cache-api</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>3.8.1</version>
        </dependency>
        <!--DATABASE-->
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>3.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.18.1</version>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.19.Final</version>
        </dependency>
        <dependency>
            <groupId>org.passay</groupId>
            <artifactId>passay</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>2.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.sanctionco.jmail</groupId>
            <artifactId>jmail</artifactId>
            <version>1.3.2</version>
        </dependency>
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
            <version>2.10.13</version>
        </dependency>
        <!--AOP-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
        </dependency>
    </dependencies>

    <profiles>
        <profile>
            <id>dev</id>
            <properties>
                <activatedProperties>dev</activatedProperties>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <profile>
            <id>test</id>
            <properties>
                <activatedProperties>test</activatedProperties>
            </properties>
            <dependencies>
                <dependency>
                    <groupId>com.h2database</groupId>
                    <artifactId>h2</artifactId>
                    <version>1.4.191</version>
                </dependency>
            </dependencies>
        </profile>
    </profiles>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                    <excludeDevtools>false</excludeDevtools>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <trimStackTrace>false</trimStackTrace>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>${aspectj-maven-plugin.version}</version>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <showWeaveInfo>true</showWeaveInfo>
                    <Xlint>ignore</Xlint>
                    <verbose>true</verbose>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <complianceLevel>${java.version}</complianceLevel>
                    <encoding>utf-8</encoding>
                    <outxml>true</outxml>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                    <excludes>
                        <exclude>**/*.java</exclude>
                    </excludes>
                    <forceAjcCompile>true</forceAjcCompile>
                    <sources/>
                    <weaveDirectories>
                        <weaveDirectory>${project.build.outputDirectory}</weaveDirectory>
                    </weaveDirectories>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
</project>

这是非常奇怪的情况,我找不到相关信息。你能帮忙找出原因吗?

最佳答案

我无法重现该问题,因为 IDEA 找不到 Lombok setter。即使在运行之前将构建操作委托(delegate)给 Maven,我也会收到 NoSuchMethodError: '...TestEntity.setCode(java.lang.String)'。接下来,我将尝试不使用 Lombok。请注意,Lombok 和 AspectJ 不能很好地配合,请参阅 my answer here 。或者,您还可以确保 Maven 执行以下任一操作:

  1. 首先使用 Javac + Lombok 进行构建,然后在第二步中应用 AspectJ 二进制编织,所有这些都在一个模块中。
  2. 与上面类似,但在模块 A 中执行第一个构建步骤,在单独的模块 B 中执行第二个构建步骤。然后您将获得一个未编织和一个编织的工件,您可以根据自己的喜好使用它们。例如,您还可以使用未编织的方式,并在启动应用程序时通过加载时编织 (LTW) 应用事务方面。请参阅my other answer here对于方法 #1 和方法 #2。
  3. Delombok 源代码在第二个构建步骤中使用 AspectJ 编译器构建生成的源代码。

我在 IDE 中生成了构造函数、getter 和 setter,而不是使用 Lombok。现在该项目可以在 IDE 和 Maven 中编译。它的行为完全符合预期。使用 @Transactional 会创建 0 个实体,没有 @Transactional 则创建 2 个实体。

我不确定 Lombok 与 AspectJ 是否真的是由于使用 Lombok 注释时的不可编译性而导致的问题,但对于您来说,在没有 Lombok 的情况下尝试应该很容易。如果它在您的环境中也有效,我们就找到了罪魁祸首,并且可以考虑实现上述 3 种方法之一。然后你可以告诉我如果你这样做有什么困难。


更新:我在我的 fork 中为您创建了两个模块版本 - Javac + Lombok,然后是 Aspect weaving,并且还发布了 pull request #1 。我还稍微提高了可测试性。看看这是否适合您。

警告:您不能简单地从 application-lombok 模块运行 DemoApplication,因为该模块仍处于未编织状态,不会显示事务行为。但是您可以简单地将运行配置的类路径更改为 application-aspectj 模块:

IntelliJ IDEA run configuration


更新:正如我们在另一个答案的评论部分中发现的那样,除了 Lombok 与 AspectJ 编译器配置有问题之外,OP 的 IDE 也有问题:使用 IntelliJ IDEA Community Edition,他首先不知道,然后无法安装 AspectJ 插件,这意味着 IDEA 不知道 AspectJ 编译器的任何信息,只是简单地用普通 Java 类覆盖了 AspectJ Maven 之前可能编译的任何内容。因此,事务方面也不起作用,除非

  • 禁用预运行编译,并启动 mvncompile 作为相应运行配置的附加预构建步骤,
  • 或者项目的所有构建操作都通过配置委托(delegate)给 Maven,
  • OP 购买 IDEA Ultimate 许可证并安装 AspectJ 插件。

关于Spring 方面由 AspectJ 编译器编织,可在 Maven 中工作,但不能在 IntelliJ IDEA 中工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70436706/

相关文章:

java - 是否可以在编译时将 AspectJ 编织到 WAR 打包项目中?

spring - 如何在spring boot中查看schema sql(DDL)?

java - 如何允许匿名访问@RequestMapping?

spring - Primefaces 文件上传仅适用于要上传的第一个文件

android-studio - 安卓工作室 : How to wrap code in parenthesis

java - 有没有办法将巨大的 Java 变量保留在内存中以节省加载时间?

intellij-idea - 想法 : How to create toString() using superclass

java - 纯 AspectJ 加载时间编织不起作用

java - 将 AOP 功能添加到 Spring 项目后,未找到合格的 Bean 错误

java - "is an unknown property": custom properties in Spring's application. 属性