首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将AspectJ java项目编织到Spring boot项目中

如何将AspectJ java项目编织到Spring boot项目中
EN

Stack Overflow用户
提问于 2021-06-19 02:44:49
回答 1查看 306关注 0票数 0

我有一个名为测试的java项目,其中包含了所有的方面。我想在另一个spring boot项目中使用这些方面。我正在开发一个poc,将测试项目中的各个方面编织成一个spring boot应用程序。这样做的有效方法是什么,以及如何做到这一点,请实现的人建议。

使用方面测试Java项目的代码

代码语言:javascript
运行
复制
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Secured {
    public boolean isLocked() default false; 
}
代码语言:javascript
运行
复制
@Aspect
public class SecuredMethodAspect {

    @Pointcut("@annotation(secured)")
    public void callAt(Secured secured) {}

    @Around("callAt(secured)")
    public Object around(ProceedingJoinPoint pjp, Secured secured) throws Throwable {
        if (secured.isLocked()) {
             System.out.println(pjp.getSignature().toLongString() + " is locked");
            return pjp.proceed();
        } else {
            return pjp.proceed();
        }
    }
}
代码语言:javascript
运行
复制
        <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>
    
        <groupId>aspect</groupId>
        <artifactId>test</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>AspectJ-POC</name>
        <url>http://maven.apache.org</url>
    
        <properties>
            <maven.compiler.source>11</maven.compiler.source>
            <maven.compiler.target>11</maven.compiler.target>
            <java.version>11</java.version>
        </properties>
    
        <!-- nickwongdev aspectj maven plugin, this is for weaving of aspects -->
        <build>
            <plugins>
                <plugin>
                    <groupId>com.nickwongdev</groupId>
                    <artifactId>aspectj-maven-plugin</artifactId>
                    <version>1.12.6</version>
                    <configuration>
                        <source>11</source>
                        <target>11</target>
                        <complianceLevel>11</complianceLevel>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>compile</goal>
                                <goal>test-compile</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
        <!-- aspectj runtime dependency -->
        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>1.9.6</version>
            </dependency>
        </dependencies>
    
    </project>
EN

回答 1

Stack Overflow用户

发布于 2021-07-12 11:26:05

在克隆之前浏览你的项目时,我得到了一些快速的第一印象:

在编译时编织场景中,你不应该同时使用Lombok +原生AspectJ,请参见

  • 变通办法是多阶段编译,即首先使用AspectJ + Lombok,然后使用AspectJ进行编译后编织,请参阅my answer here。或者,首先使用delombok生成源代码,并将Lombok注释展开为等价的源代码,然后使用AspectJ编译生成的源代码。
  • 再看一下,您的示例方面模块似乎没有使用任何Lombok,因此您不需要该依赖项。当然,你可以使用编译时编织来编织你的方面,就像你建议的那样。
  • 当然,你可以使用编译时编织来编织你的方面。在这种情况下,您需要正确配置AspectJ Maven插件,但您没有这样做。除了主应用程序之外,还需要在Spring Boot模块中告诉它在哪里可以找到方面库,以及要编织哪些依赖项。你有没有读过插件文档,比如Weaving classes in jarsUsing aspect librariesMulti-module use of AspectJ?我在这里已经回答了大量的相关问题。
  • ,但实际上,将方面编织到Spring应用程序中的首选方法是使用加载时编织( load-time weaving ),如Spring manual中所述。这应该更容易配置,而且您不需要任何Lombok插件,并且在编译过程中可能也不会出现任何AspectJ问题。

从您的样例项目和您的AspectJ Maven配置中没有任何aspectLibrariesweaveDependencies部分判断,您根本没有阅读任何文档,这让我想知道您在试图使其正常工作的一个月内做了什么。

我想发表一个评论,解释为什么你想使用CTW而不是LTW。我能想到的唯一原因是,除了原生方面之外,您还希望在Spring应用程序中使用Spring AOP方面。但是如果你激活了原生AspectJ LTW,你就不能同时使用Spring AOP了。如果这不是问题,我推荐LTW,因为它在Spring中有很好的文档记录和测试。CTW也不是问题,但在你的POMs中更难理解和管理。

更新:好的,我不想再因为你的原因而等待了,我决定向你展示一个LTW解决方案。我所做的是:

  • 从您的AspectJ项目中移除Spring Maven插件和AspectJ工具
  • Add src/main/resources/org/aspectj/aop.xml,将其配置为使用您的方面,并针对您的基包+Spring切入点也使用您的基包+子包,因为在您的基包中没有类。这是一个典型的初学者的错误。您需要将execution(* com.ak..*(..))..一起使用,而不仅仅是com.ak.*.

我使用的非必需品有:

  • 从Spring Boot应用程序的main方法调用context.getBean(TestController.class).mainRequest(),以便自动生成某些方面输出,以避免必须使用curl或web浏览器来调用本地URL.
  • 使用Spring应用程序作为一个可通过try- output.
  • Change -resources自动关闭的应用程序,以便在创建所需的日志后关闭应用程序,并记录方面,以便在日志中查看它实际截获的方法。否则,所有日志行看起来都是一样的,这不是很有帮助。
  • 使用try-finally,以确保在进入原始方法后,在发生异常时也记录日志消息。

diff看起来像这样(我希望你能读懂diff):

代码语言:javascript
运行
复制
diff --git a/aspect-test-project/src/main/java/com/ak/aspect/MethodLogAspect.java b/aspect-test-project/src/main/java/com/ak/aspect/MethodLogAspect.java
--- a/aspect-test-project/src/main/java/com/ak/aspect/MethodLogAspect.java  (revision Staged)
+++ b/aspect-test-project/src/main/java/com/ak/aspect/MethodLogAspect.java  (date 1626233247623)
@@ -7,14 +7,14 @@
 @Aspect
 public class MethodLogAspect {
 
-   @Around("@annotation( MethodLog) && (execution(* com.ak.*(..)))")
+   @Around("@annotation(MethodLog) && execution(* com.ak..*(..))")
    public Object wrap(final ProceedingJoinPoint joinPoint) throws Throwable {
-       System.out.println("***Aspect invoked before calling method***");
-       
-       final Object obj = joinPoint.proceed();
-       
-       System.out.println("***Aspect invoked after calling method***");
-       
-       return obj;
+       System.out.println("[BEFORE] " + joinPoint);
+       try {
+           return joinPoint.proceed();
+       }
+       finally {
+       System.out.println("[AFTER]  " + joinPoint);
+       }
    }
 }
diff --git a/src/main/java/com/ak/ParentprojectSpringbootApplication.java b/src/main/java/com/ak/ParentprojectSpringbootApplication.java
--- a/src/main/java/com/ak/ParentprojectSpringbootApplication.java  (revision Staged)
+++ b/src/main/java/com/ak/ParentprojectSpringbootApplication.java  (date 1626233555873)
@@ -1,14 +1,17 @@
 package com.ak;
 
+import com.ak.controller.TestController;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.ConfigurableApplicationContext;
 
 @SpringBootApplication(scanBasePackages = { "com.ak.*" })
-//@SpringBootApplication
 public class ParentprojectSpringbootApplication {
 
    public static void main(String[] args) {
-       SpringApplication.run(ParentprojectSpringbootApplication.class, args);
+       try (ConfigurableApplicationContext context = SpringApplication.run(ParentprojectSpringbootApplication.class, args)) {
+           context.getBean(TestController.class).mainRequest();
+       }
    }
 
 }
diff --git a/parentproject-springboot/pom.xml b/parentproject-springboot/pom.xml
--- a/parentproject-springboot/pom.xml  (revision Staged)
+++ b/parentproject-springboot/pom.xml  (date 1626232421474)
@@ -71,13 +71,6 @@
            <version>1.9.6</version>
        </dependency>
 
-       <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools -->
-       <dependency>
-           <groupId>org.aspectj</groupId>
-           <artifactId>aspectjtools</artifactId>
-           <version>1.9.6</version>
-       </dependency>
-
        <dependency>
            <groupId>com.ak.aspect</groupId>
            <artifactId>aspect-test-project</artifactId>
@@ -100,24 +93,6 @@
                </configuration>
            </plugin>
 
-           <plugin>
-               <groupId>com.nickwongdev</groupId>
-               <artifactId>aspectj-maven-plugin</artifactId>
-               <version>1.12.6</version>
-               <configuration>
-                   <source>11</source>
-                   <target>11</target>
-                   <complianceLevel>11</complianceLevel>
-               </configuration>
-               <executions>
-                   <execution>
-                       <goals>
-                           <goal>compile</goal>
-                           <goal>test-compile</goal>
-                       </goals>
-                   </execution>
-               </executions>
-           </plugin>
        </plugins>
    </build>

为了方便起见,下面是完整的更改文件:

代码语言:javascript
运行
复制
<?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.2</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.ak</groupId>
    <artifactId>parentproject-springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>parentproject-springboot</name>
    <description>Test project for Spring Boot</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </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-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.ak.dependency</groupId>
            <artifactId>dependencyprojet</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

        <!-- aspectj runtime dependency -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.9.6</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>

        <dependency>
            <groupId>com.ak.aspect</groupId>
            <artifactId>aspect-test-project</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <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>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>
代码语言:javascript
运行
复制
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>

    <weaver options="-verbose -showWeaveInfo">
        <!-- only weave classes in our application-specific packages -->
        <include within="com.ak..*"/>
    </weaver>

    <aspects>
        <aspect name="com.ak.aspect.MethodLogAspect"/>
    </aspects>

</aspectj>
代码语言:javascript
运行
复制
package com.ak.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MethodLogAspect {

    @Around("@annotation(MethodLog) && execution(* com.ak..*(..))")
    public Object wrap(final ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("[BEFORE] " + joinPoint);
        try {
            return joinPoint.proceed();
        }
        finally {
        System.out.println("[AFTER]  " + joinPoint);
        }
    }
}
代码语言:javascript
运行
复制
package com.ak;

import com.ak.controller.TestController;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication(scanBasePackages = { "com.ak.*" })
public class ParentprojectSpringbootApplication {

    public static void main(String[] args) {
        try (ConfigurableApplicationContext context = SpringApplication.run(ParentprojectSpringbootApplication.class, args)) {
            context.getBean(TestController.class).mainRequest();
        }
    }

}

现在,您只需确保将-javaagent:/path/to/aspectjweaver-1.9.6.jar参数添加到您的AspectJ命令行,以便激活本机Java即可。有关如何在Spring中以更复杂的方式配置LTW的更多详细信息,请阅读Spring手册中的Using AspectJ with Spring Applications部分。

控制台日志应如下所示:

代码语言:javascript
运行
复制
[AppClassLoader@3764951d] info AspectJ Weaver Version 1.9.6 built on Tuesday Jul 21, 2020 at 13:30:08 PDT
[AppClassLoader@3764951d] info register classloader jdk.internal.loader.ClassLoaders$AppClassLoader@3764951d
[AppClassLoader@3764951d] info using configuration /C:/Users/alexa/Documents/java-src/SO_AJ_SpringCTWMultiModule_68040124/parentproject-springboot/target/classes/org/aspectj/aop.xml
[AppClassLoader@3764951d] info register aspect com.ak.aspect.MethodLogAspect
[AppClassLoader@3764951d] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
[RestartClassLoader@1f385e10] info AspectJ Weaver Version 1.9.6 built on Tuesday Jul 21, 2020 at 13:30:08 PDT
[RestartClassLoader@1f385e10] info register classloader org.springframework.boot.devtools.restart.classloader.RestartClassLoader@1f385e10
[RestartClassLoader@1f385e10] info using configuration /C:/Users/alexa/Documents/java-src/SO_AJ_SpringCTWMultiModule_68040124/parentproject-springboot/target/classes/org/aspectj/aop.xml
[RestartClassLoader@1f385e10] info register aspect com.ak.aspect.MethodLogAspect

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.5.2)

(...)
[RestartClassLoader@1f385e10] weaveinfo Join point 'method-execution(com.ak.dependency.model.AccountInfo com.ak.service.TestService.incomingRequest())' in Type 'com.ak.service.TestService' (TestService.java:20) advised by around advice from 'com.ak.aspect.MethodLogAspect' (MethodLogAspect.java)
[RestartClassLoader@1f385e10] weaveinfo Join point 'method-execution(com.ak.dependency.model.AccountInfo com.ak.dependency.Route.accountInfo())' in Type 'com.ak.dependency.Route' (Route.java:12) advised by around advice from 'com.ak.aspect.MethodLogAspect' (MethodLogAspect.java)
[RestartClassLoader@1f385e10] weaveinfo Join point 'method-execution(com.ak.dependency.model.BalanceInfo com.ak.dependency.Pipeline.balanceInfo())' in Type 'com.ak.dependency.Pipeline' (Pipeline.java:11) advised by around advice from 'com.ak.aspect.MethodLogAspect' (MethodLogAspect.java)
(...)

Controller
[BEFORE] execution(AccountInfo com.ak.service.TestService.incomingRequest())
[BEFORE] execution(AccountInfo com.ak.dependency.Route.accountInfo())
[BEFORE] execution(BalanceInfo com.ak.dependency.Pipeline.balanceInfo())
[AFTER]  execution(BalanceInfo com.ak.dependency.Pipeline.balanceInfo())
[AFTER]  execution(AccountInfo com.ak.dependency.Route.accountInfo())
[AFTER]  execution(AccountInfo com.ak.service.TestService.incomingRequest())
(...)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68040124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档