2 回答
TA贡献1828条经验 获得超3个赞
我一发布这个,我就尝试用以下命令更改 ReviewTask 和 AnnotationTask
@Override
public Object task( ProceedingJoinPoint proceedingJoinPoint, JobContext context ) throws Throwable {
log.info( "ReviewTask's task" );
/*
* do some validation if annotation is completed or not
*/
log.info( "not completing the review task due to some reason" );
context.setReviewTaskStatus( TaskStatus.IN_PROGRESS );
return proceedingJoinPoint.proceed();
}
这解决了我的问题。
TA贡献1752条经验 获得超4个赞
你是对的,我刚刚注意到 TaskAspects 根本没有被触发。我没有看到来自 TaskAspects 的任何日志。我可以在没有任何 spring-aop 的情况下在 spring-boot 中使用 AspectJ 吗?感谢您的查看并通知。非常赞赏。
基本上,您只需从要通过 AspectJ 使用的方面中删除@Component注释,并将这些方面添加到文件src/main/resources/org/aspectj/aop.xml(假设您使用 Maven 来构建项目):
<!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.spring.aspect.dynamicflow..*"/>
</weaver>
<aspects>
<aspect name="com.spring.aspect.dynamicflow.aspect.TaskAspects"/>
<aspect name="com.spring.aspect.dynamicflow.activity.AnnotationTask"/>
<aspect name="com.spring.aspect.dynamicflow.activity.ReviewTask"/>
</aspects>
</aspectj>
然后你开始你的应用程序-javaagent:/path/to/aspectjweaver.jar
,例如:
-javaagent:"c:\Users\me\.m2\repository\org\aspectj\aspectjweaver\1.9.4\aspectjweaver-1.9.4.jar"
您还可以在 Java 命令行上同时使用 AspectJ Weaver 和 Spring Instrument 这两个代理,例如
-javaagent:"c:\Users\me\.m2\repository\org\aspectj\aspectjweaver\1.9.4\aspectjweaver-1.9.4.jar" -javaagent:"c:\Program Files\Java\spring-framework-5.1.9.RELEASE\libs\spring-instrument-5.1.9.RELEASE.jar"
为了您的方便,并且为了自己拥有一个示例项目,我在GitHub 存储库中共享了我的工作示例。有一个Spring AOP 分支和另一个AspectJ LTW 分支。这些分支之间的差异如下所示:
diff --git a/src/main/java/com/spring/aspect/dynamicflow/Application.java b/src/main/java/com/spring/aspect/dynamicflow/Application.java
index 2a7021e..3a7636f 100644
--- a/src/main/java/com/spring/aspect/dynamicflow/Application.java
+++ b/src/main/java/com/spring/aspect/dynamicflow/Application.java
@@ -8,6 +8,16 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
+/**
+ * Run this from your IDE with
+ *
+ * a) either just -javaagent:/path/to/aspectjweaver.jar and without @EnableLoadTimeWeaving
+ *
+ * b) or with both -javaagent:/path/to/aspectjweaver.jar -javaagent:/path/to/spring-instrument.jar,
+ * either with or without @EnableLoadTimeWeaving. What benefit this has, I don't know.
+ *
+ * See also my extensive comment in Application class.
+ */
@SpringBootApplication
public class Application {
private static final Logger log = LoggerFactory.getLogger(Application.class);
diff --git a/src/main/java/com/spring/aspect/dynamicflow/ApplicationConfig.java b/src/main/java/com/spring/aspect/dynamicflow/ApplicationConfig.java
index b4698e1..649a6ca 100644
--- a/src/main/java/com/spring/aspect/dynamicflow/ApplicationConfig.java
+++ b/src/main/java/com/spring/aspect/dynamicflow/ApplicationConfig.java
@@ -3,8 +3,34 @@ package com.spring.aspect.dynamicflow;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.context.annotation.EnableLoadTimeWeaving;
+import static org.springframework.context.annotation.EnableLoadTimeWeaving.AspectJWeaving.ENABLED;
+
+/**
+ * Remarks about AspectJ load-time weaving(LTW) in Spring:
+ *
+ * According to the Spring manual it should be enough to put spring-instrument.jar is on the JVM command line
+ * in combination with @EnableLoadTimeWeaving. Actually this does help Spring detect the AspectJ weaver,
+ * I can see the aspects loaded. But obviously this happens too late after the application classes are
+ * already loaded, so the aspects do not have any effect. I even added a static block
+ * static { logger.info("JobProcessImpl class was loaded"); } to JobProcessImpl in order to check it an
+ * the log output occurs right before the aspects are being activated, which of course is too late.
+ *
+ * LTW works if
+ *
+ * a) either I have both Java agents aspectjweaver.jar and spring-instrument.jar on JVM command line
+ * in combination with @EnableLoadTimeWeaving (but then it tries to weave twice, I can see errors in the log)
+ * or without @EnableLoadTimeWeaving (no errors in the log)
+ *
+ * b) or if I only use aspectjweaver.jar without @EnableLoadTimeWeaving.
+ *
+ * The latter is no surprise because AspectJ is independent of Spring and of course works even if Spring is
+ * unaware of its presence. But if I want to advertise its presence via @EnableLoadTimeWeaving, I do not
+ * understand why spring-instrument.jar is not enough, as described in the Spring manual.
+ */
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.spring.aspect.dynamicflow")
+//@EnableLoadTimeWeaving(aspectjWeaving = ENABLED)
public class ApplicationConfig {}
diff --git a/src/main/java/com/spring/aspect/dynamicflow/activity/AnnotationTask.java b/src/main/java/com/spring/aspect/dynamicflow/activity/AnnotationTask.java
index 3c6d5c4..bbdd5b1 100644
--- a/src/main/java/com/spring/aspect/dynamicflow/activity/AnnotationTask.java
+++ b/src/main/java/com/spring/aspect/dynamicflow/activity/AnnotationTask.java
@@ -6,9 +6,7 @@ import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-@Component
@Aspect
public class AnnotationTask extends Task {
private static final Logger log = LoggerFactory.getLogger(AnnotationTask.class);
diff --git a/src/main/java/com/spring/aspect/dynamicflow/activity/ReviewTask.java b/src/main/java/com/spring/aspect/dynamicflow/activity/ReviewTask.java
index ece0ff6..f364da2 100644
--- a/src/main/java/com/spring/aspect/dynamicflow/activity/ReviewTask.java
+++ b/src/main/java/com/spring/aspect/dynamicflow/activity/ReviewTask.java
@@ -6,9 +6,7 @@ import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-@Component
@Aspect
public class ReviewTask extends Task {
private static final Logger log = LoggerFactory.getLogger(ReviewTask.class);
diff --git a/src/main/java/com/spring/aspect/dynamicflow/activity/Task.java b/src/main/java/com/spring/aspect/dynamicflow/activity/Task.java
index 3f1f9ce..93b3b73 100644
--- a/src/main/java/com/spring/aspect/dynamicflow/activity/Task.java
+++ b/src/main/java/com/spring/aspect/dynamicflow/activity/Task.java
@@ -6,9 +6,7 @@ import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-@Component
@Aspect
public abstract class Task {
private static final Logger log = LoggerFactory.getLogger(Task.class);
diff --git a/src/main/java/com/spring/aspect/dynamicflow/aspect/TaskAspects.java b/src/main/java/com/spring/aspect/dynamicflow/aspect/TaskAspects.java
index 3bff7b5..a09d9d6 100644
--- a/src/main/java/com/spring/aspect/dynamicflow/aspect/TaskAspects.java
+++ b/src/main/java/com/spring/aspect/dynamicflow/aspect/TaskAspects.java
@@ -5,9 +5,7 @@ import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-@Component
@Aspect
public class TaskAspects {
private static final Logger log = LoggerFactory.getLogger(TaskAspects.class);
diff --git a/src/main/resources/org/aspectj/aop.xml b/src/main/resources/org/aspectj/aop.xml
new file mode 100644
index 0000000..56342b4
--- /dev/null
+++ b/src/main/resources/org/aspectj/aop.xml
@@ -0,0 +1,15 @@
+<!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.spring.aspect.dynamicflow..*"/>
+ </weaver>
+
+ <aspects>
+ <aspect name="com.spring.aspect.dynamicflow.aspect.TaskAspects"/>
+ <aspect name="com.spring.aspect.dynamicflow.activity.AnnotationTask"/>
+ <aspect name="com.spring.aspect.dynamicflow.activity.ReviewTask"/>
+ </aspects>
+
+</aspectj>
Task顺便说一句,我也很快尝试获得 Spring AOP 方面(子类)和 AspectJ 方面的组合( TaskAspects,真是一个可怕的名字,为什么不TasksAspect或TaskInterceptor?)。尽管 Spring 手册和邮件列表上的许多用户都说,即使没有额外的配置,也很容易结合这两种方法,但我无法让它按照我想要的方式运行。所以目前我还没有解决方案。也许我只是犯了一个小错误。我是一名 AspectJ 专家,但实际上从未使用过 Spring 或 Spring AOP,抱歉。
更新:我忘了提及,在我的存储库中我还解决了我之前在评论中提到的这个问题:
如果你真的使用 AspectJ LTW 场景,你的 TaskAspects 方面会被频繁触发,因为within(com.spring.aspect.dynamicflow.activity.Task+)在 AspectJ 中不仅拦截方法执行,还拦截对象和类初始化、字段访问、对其他类的方法调用等。所以要么你使用 AspectJ LTW,它也会打印很多或(...)
如果您使用该切入点,这确实是正确的。日志输出(时间戳、日志通道信息等,从日志输出中切断)将是:
Handling the task aspects.
staticinitialization(com.spring.aspect.dynamicflow.activity.Task.<clinit>)
Handling the task aspects.
call(Logger org.slf4j.LoggerFactory.getLogger(Class))
Handling the task aspects.
set(Logger com.spring.aspect.dynamicflow.activity.Task.log)
Handling the task aspects.
staticinitialization(com.spring.aspect.dynamicflow.activity.AnnotationTask.<clinit>)
Handling the task aspects.
call(Logger org.slf4j.LoggerFactory.getLogger(Class))
Handling the task aspects.
set(Logger com.spring.aspect.dynamicflow.activity.AnnotationTask.log)
Handling the task aspects.
execution(com.spring.aspect.dynamicflow.activity.Task())
Handling the task aspects.
execution(com.spring.aspect.dynamicflow.activity.AnnotationTask())
Handling the task aspects.
execution(Object com.spring.aspect.dynamicflow.activity.AnnotationTask.task(ProceedingJoinPoint, JobContext))
Handling the task aspects.
get(Logger com.spring.aspect.dynamicflow.activity.AnnotationTask.log)
Handling the task aspects.
call(void org.slf4j.Logger.info(String))
AnnotationTask's task
Handling the task aspects.
get(Logger com.spring.aspect.dynamicflow.activity.AnnotationTask.log)
Handling the task aspects.
call(void org.slf4j.Logger.info(String))
Setting that the annotation is done.
Handling the task aspects.
get(TaskStatus com.spring.aspect.dynamicflow.entity.TaskStatus.COMPLETED)
Handling the task aspects.
call(void com.spring.aspect.dynamicflow.entity.JobContext.setAnnotationTaskStatus(TaskStatus))
Handling the task aspects.
call(Object org.aspectj.lang.ProceedingJoinPoint.proceed())
Handling the task aspects.
staticinitialization(com.spring.aspect.dynamicflow.activity.ReviewTask.<clinit>)
Handling the task aspects.
call(Logger org.slf4j.LoggerFactory.getLogger(Class))
Handling the task aspects.
set(Logger com.spring.aspect.dynamicflow.activity.ReviewTask.log)
Handling the task aspects.
execution(com.spring.aspect.dynamicflow.activity.Task())
Handling the task aspects.
execution(com.spring.aspect.dynamicflow.activity.ReviewTask())
Handling the task aspects.
execution(Object com.spring.aspect.dynamicflow.activity.ReviewTask.task(ProceedingJoinPoint, JobContext))
Handling the task aspects.
get(Logger com.spring.aspect.dynamicflow.activity.ReviewTask.log)
Handling the task aspects.
call(void org.slf4j.Logger.info(String))
ReviewTask's task
Handling the task aspects.
get(Logger com.spring.aspect.dynamicflow.activity.ReviewTask.log)
Handling the task aspects.
call(void org.slf4j.Logger.info(String))
Setting that the review is done.
Handling the task aspects.
get(TaskStatus com.spring.aspect.dynamicflow.entity.TaskStatus.IN_PROGRESS)
Handling the task aspects.
call(void com.spring.aspect.dynamicflow.entity.JobContext.setReviewTaskStatus(TaskStatus))
Handling the task aspects.
call(Object org.aspectj.lang.ProceedingJoinPoint.proceed())
Processing the job with jobid 11
我还从日志行之间删除了 AspectJ weaver 日志消息(其中一些是错误)。within(com.spring.aspect.dynamicflow.activity.Task+) && execution(* task(..))您会看到 29x“处理任务方面”,而不是仅 2x,这就是我为您更改切入点的原因。现在日志输出看起来符合预期:
Handling the task aspects.
execution(Object com.spring.aspect.dynamicflow.activity.AnnotationTask.task(ProceedingJoinPoint, JobContext))
AnnotationTask's task
Setting that the annotation is done.
Handling the task aspects.
execution(Object com.spring.aspect.dynamicflow.activity.ReviewTask.task(ProceedingJoinPoint, JobContext))
ReviewTask's task
Setting that the review is done.
Processing the job with jobid 11
添加回答
举报