我有一个名为测试的java项目,其中包含了所有的方面。我想在另一个spring boot项目中使用这些方面。我正在开发一个poc,将测试项目中的各个方面编织成一个spring boot应用程序。这样做的有效方法是什么,以及如何做到这一点,请实现的人建议。
使用方面测试Java项目的代码
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Secured {
public boolean isLocked() default false;
}
@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();
}
}
}
<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>
发布于 2021-07-12 11:26:05
在克隆之前浏览你的项目时,我得到了一些快速的第一印象:
在编译时编织场景中,你不应该同时使用Lombok +原生AspectJ,请参见
delombok
生成源代码,并将Lombok注释展开为等价的源代码,然后使用AspectJ编译生成的源代码。从您的样例项目和您的AspectJ Maven配置中没有任何aspectLibraries
和weaveDependencies
部分判断,您根本没有阅读任何文档,这让我想知道您在试图使其正常工作的一个月内做了什么。
我想发表一个评论,解释为什么你想使用CTW而不是LTW。我能想到的唯一原因是,除了原生方面之外,您还希望在Spring应用程序中使用Spring AOP方面。但是如果你激活了原生AspectJ LTW,你就不能同时使用Spring AOP了。如果这不是问题,我推荐LTW,因为它在Spring中有很好的文档记录和测试。CTW也不是问题,但在你的POMs中更难理解和管理。
更新:好的,我不想再因为你的原因而等待了,我决定向你展示一个LTW解决方案。我所做的是:
src/main/resources/org/aspectj/aop.xml
,将其配置为使用您的方面,并针对您的基包+Spring切入点也使用您的基包+子包,因为在您的基包中没有类。这是一个典型的初学者的错误。您需要将execution(* com.ak..*(..))
与..
一起使用,而不仅仅是com.ak.*
.我使用的非必需品有:
context.getBean(TestController.class).mainRequest()
,以便自动生成某些方面输出,以避免必须使用curl
或web浏览器来调用本地URL.try-finally
,以确保在进入原始方法后,在发生异常时也记录日志消息。diff看起来像这样(我希望你能读懂diff):
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>
为了方便起见,下面是完整的更改文件:
<?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>
<!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>
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);
}
}
}
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部分。
控制台日志应如下所示:
[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())
(...)
https://stackoverflow.com/questions/68040124
复制相似问题