我试图让一个springboot(2.6.2)项目同时使用AspectJ和Spring AOP。
我有以下示例类:
第一个
我的pom.xml文件定义了以下插件:
<plugin>
<groupId>com.nickwongdev</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.12.6</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<proc>none</proc>
<complianceLevel>${java.version}</complianceLevel>
<showWeaveInfo>true</showWeaveInfo>
<forceAjcCompile>true</forceAjcCompile>
<sources/>
<weaveDirectories>
<weaveDirectory>${project.build.directory}/classes</weaveDirectory>
</weaveDirectories>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.18.20.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>delombok</goal>
</goals>
</execution>
</executions>
<configuration>
<addOutputDirectory>false</addOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
我还定义了一个src/main/resources/org/aspectj/aop.xml:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<include within="mypackage..*" />
<include within="org.springframework.boot..*" />
</weaver>
<aspects>
<aspect name="mypackage.MyAspect" />
</aspects>
</aspectj>
它看起来编译正常,我看到了正在建议连接点的信息消息。但是,在OtherAspect中,自动连接的MyUtility没有得到设置。
从我所能找到的内容来看,我希望Spring将OtherAspect识别为一个组件,并在MyUtility中自动连接,但我得到了一个NullPointerException。
有什么想法吗?谢谢!
1条答案
按热度按时间g6ll5ycj1#
好的,我花了一点时间准备了MCVE,这实际上是你的工作。我做了以下假设:
1.您需要原生AspectJ,因为您希望编织一个不是Springbean的目标类。
1.您希望使用编译时,而不是加载时的weaving。因此,您将使用AspectJ Maven插件。
1.您希望使用Spring依赖注入将Springbean连接到本机AspectJ方面,如Spring手册中所述,即在Spring中为本机方面使用
aspectOf
工厂方法。1.您绝对坚持要将Lombok和原生AspectJ结合起来,即使它们是incompatible out of the box。也就是说,您需要在Maven中找到一个解决方法,要么是二进制编织(例如,如果Lombok只用于您的非方面类),要么是“delombok”构建步骤(例如,如果您的方面也使用Lombok,不幸的是,它们确实使用
MyAspect
中的@Slf4j
Lombok注解)。我在设置中更改的内容:
Item
中的@Entity
和@Id
注解。${project.build.directory}/generated-sources/delombok
作为源目录时,您的示例代码只能使用AspectJMaven进行编译。您使用<weaveDirectory>
的想法行不通,因为带有Lombok注解的方面不能以这种方式进行编译。因为它引用Lombok生成的静态log
字段。@Service
注解,因为这会导致连接应用程序时出现问题。相反,我向OtherAspect
添加了一个@Bean
工厂方法,因此我们可以在那里使用@Autowired MyUtility myUtility
。在同一方面,我还从@annotation(SystemCall)
(由于您的示例中缺少代码)切换到@annotation(Verify.Access)
,以便有一些东西可供测试。com.nickwongdev
AspectJ Maven插件切换到了当前的dev.aspectj
插件,它具有更多的特性,也支持Java 17+。整个应用程序如下所示:
第一个问题
如果运行Sping Boot 应用程序,您将在控制台上看到以下内容(已删除时间戳):
正如您所看到的,两个方面都起作用,第一个方面记录ERROR,另一个方面将返回值从“my name”更改为“my info”。
“delombok”变体的优点是,在同一个Maven模块中,您可以将方面编织到Lolbok生成的源代码中。缺点是,在您的IDE中,您可能无法编译从Maven导入的项目,因为自定义配置非常不寻常。在IntelliJ IDEA中,我不得不将构建委托给Maven,但源代码编辑器仍然显示扭曲的线条。
或者,您可以使用Lombok编译创建一个模块(没有“delombok”),第二个模块使用二进制编织,以便将方面编织到Lombok增强的类文件中,如here所述。第三种选择是使用Lombok和为 Boot 配置的本机AspectJ加载时编织进行编译,而不是编译。我不能在这里详细解释和展示每一个变体,这已经是一个很长的答案了。