Spring aop:为子类定义了切入点但只调用了一个子类

Object process( JobContext jobContext );我使用名为 JobProcessImpl 的 impl 的方法定义 JobProcess 。每当执行此 JobProcessImpl.process 方法时,我都想监视多个子类。我希望所有这些子类都被执行。


间谍类被定义为基类Task来查找 JobProcessImpl.process 调用。


在输出中,我总是看到仅从 AnnotationTask 记录,而不从 ReviewTask 记录。


请告诉我,如果可能的话,问题是什么。


我尝试了两天通过关注各种帖子来解决这个问题。


package com.spring.aspect.dynamicflow.activity;


import com.spring.aspect.dynamicflow.entity.JobContext;

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 );


    @Around ( "execution(public java.lang.Object com.spring.aspect.dynamicflow.process.JobProcessImpl.process(..)) " + "&& args(context)" )

    public Object task( JobContext context ) {

        log.info( "This is the base task and needs to overridden by the derived task for the job id: {} ", context.getJobId() );


        return  context;

    }

}

基类:AnnotationTask


package com.spring.aspect.dynamicflow.activity;


import com.spring.aspect.dynamicflow.entity.JobContext;

import com.spring.aspect.dynamicflow.entity.TaskStatus;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;


@Component

public class AnnotationTask extends Task {


    private static final Logger log = LoggerFactory.getLogger( AnnotationTask.class );


    @Override

    public Object task( JobContext context ) {

        log.info( "AnnotationTask's task" );


        /*

         * do some validation if annotation is completed or not

         */


        log.info( "Setting that the annotation is done." );

        context.setAnnotationTaskStatus( TaskStatus.COMPLETED );

        return "AnnotationTask Completed";

    }


蝴蝶不菲
浏览 152回答 2
2回答

倚天杖

我一发布这个,我就尝试用以下命令更改 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();    }这解决了我的问题。

温温酱

你是对的,我刚刚注意到 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.javaindex 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.javaindex 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.javaindex 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.javaindex 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.javaindex 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.javaindex 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.xmlnew file mode 100644index 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 taskHandling 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 taskHandling 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
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java