支持aspectj和Spring AOP的Springboot

fgw7neuy  于 2022-12-04  发布在  Spring
关注(0)|答案(1)|浏览(145)

我试图让一个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。
有什么想法吗?谢谢!

g6ll5ycj

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注解)。
我在设置中更改的内容:

  • 我删除了对Spring Data JPA的依赖以使事情变得更简单,因为我懒得设置一个虚拟的内存中数据库。这与这里的解决方案无关。也就是说,我还注解掉了类Item中的@Entity@Id注解。
  • 您已经配置了一个“delombok”构建步骤,我想继续使用这个步骤,因为这似乎是您的偏好。因此,当使用${project.build.directory}/generated-sources/delombok作为源目录时,您的示例代码只能使用AspectJMaven进行编译。您使用<weaveDirectory>的想法行不通,因为带有Lombok注解的方面不能以这种方式进行编译。因为它引用Lombok生成的静态log字段。
  • 我从本机AspectJ方面删除了@Service注解,因为这会导致连接应用程序时出现问题。相反,我向OtherAspect添加了一个@Bean工厂方法,因此我们可以在那里使用@Autowired MyUtility myUtility。在同一方面,我还从@annotation(SystemCall)(由于您的示例中缺少代码)切换到@annotation(Verify.Access),以便有一些东西可供测试。
  • 我删除了多余的 aop.xml 文件。
  • 我添加了一个小的Sping Boot 驱动程序。
  • 我从不再维护的com.nickwongdev AspectJ Maven插件切换到了当前的dev.aspectj插件,它具有更多的特性,也支持Java 17+。

整个应用程序如下所示:
第一个问题
如果运行Sping Boot 应用程序,您将在控制台上看到以下内容(已删除时间戳):

ERROR 20680 --- [           main] org.example.MyAspect                     : BEFORE ANNOTATION
 INFO 20680 --- [           main] org.example.Main                         : my info

正如您所看到的,两个方面都起作用,第一个方面记录ERROR,另一个方面将返回值从“my name”更改为“my info”。
“delombok”变体的优点是,在同一个Maven模块中,您可以将方面编织到Lolbok生成的源代码中。缺点是,在您的IDE中,您可能无法编译从Maven导入的项目,因为自定义配置非常不寻常。在IntelliJ IDEA中,我不得不将构建委托给Maven,但源代码编辑器仍然显示扭曲的线条。
或者,您可以使用Lombok编译创建一个模块(没有“delombok”),第二个模块使用二进制编织,以便将方面编织到Lombok增强的类文件中,如here所述。第三种选择是使用Lombok和为 Boot 配置的本机AspectJ加载时编织进行编译,而不是编译。我不能在这里详细解释和展示每一个变体,这已经是一个很长的答案了。

相关问题