首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring确定方法是否被@调度调用

Spring确定方法是否被@调度调用
EN

Stack Overflow用户
提问于 2020-12-21 17:07:41
回答 2查看 414关注 0票数 0

我有一个运行时注释@MyAnnotation,我想编写一个方面来确定下面的test()方法是否是由以下代码调用的:

  • Spring的@Scheduled
  • 方法调用

代码语言:javascript
复制
@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Scheduled(cron = "*/1 * * * * *") // scheduled to invoke every second
    @MyAnnotation
    public void test() {
        // business logic
    }
}

方面代码(切入点+通知)

代码语言:javascript
复制
    @Around(value="@annotation(myAnnotation)")
    public Object featureToggle(ProceedingJoinPoint joinPoint, MyAnnotation myAnnotation) throws Throwable {
        Boolean isInvoked = // TODO - is invoked by @Scheduled or not
    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-22 03:02:46

检查堆栈跟踪总是很难看的,但当然可以这样做:

代码语言:javascript
复制
package de.scrum_master.spring.q65397019;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {}
代码语言:javascript
复制
package de.scrum_master.spring.q65397019;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {
  @Scheduled(fixedRate = 1000)
//  @Async
  @MyAnnotation
  public void doSomething() {}
}
代码语言:javascript
复制
package de.scrum_master.spring.q65397019;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@Configuration
@EnableScheduling
@EnableAsync
public class DemoApplication {
  public static void main(String[] args) throws InterruptedException {
    try (ConfigurableApplicationContext appContext = SpringApplication.run(DemoApplication.class, args)) {
      doStuff(appContext);
    }
  }

  private static void doStuff(ConfigurableApplicationContext appContext) throws InterruptedException {
    MyComponent myComponent = appContext.getBean(MyComponent.class);
    myComponent.doSomething();
    Thread.sleep(1000);
    myComponent.doSomething();
  }
}
代码语言:javascript
复制
package de.scrum_master.spring.q65397019;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Component
public class MyAspect {
  @Around("@annotation(myAnnotation)")
  public Object advice2(ProceedingJoinPoint joinPoint, MyAnnotation myAnnotation) throws Throwable {
    if (
      Arrays.stream(new Exception().getStackTrace())
        .map(StackTraceElement::toString)
        .anyMatch(string -> string.contains("scheduling.support.ScheduledMethodRunnable.run("))
    )
      System.out.println(joinPoint + " -> scheduled");
    else
      System.out.println(joinPoint + " -> normal");
    return joinPoint.proceed();
  }
}

这将打印如下内容:

代码语言:javascript
复制
(...)
2020-12-22 10:00:59.372  INFO 1620 --- [           main] o.s.s.c.ThreadPoolTaskScheduler          : Initializing ExecutorService 'taskScheduler'
execution(void de.scrum_master.spring.q65397019.MyComponent.doSomething()) -> scheduled
2020-12-22 10:00:59.456  INFO 1620 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-12-22 10:00:59.456  INFO 1620 --- [           main] d.s.spring.q65397019.DemoApplication     : Started DemoApplication in 6.534 seconds (JVM running for 8.329)
execution(void de.scrum_master.spring.q65397019.MyComponent.doSomething()) -> normal
execution(void de.scrum_master.spring.q65397019.MyComponent.doSomething()) -> scheduled
execution(void de.scrum_master.spring.q65397019.MyComponent.doSomething()) -> normal
2020-12-22 10:01:00.475  INFO 1620 --- [           main] o.s.s.c.ThreadPoolTaskScheduler          : Shutting down ExecutorService 'taskScheduler'
2020-12-22 10:01:00.477  INFO 1620 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
(...)

在Java上,您可以使用堆栈遍历API,这比从异常实例创建完整的堆栈跟踪或从当前运行的线程查询它们更有效。

警告:--如果您也用@Async注释您的计划方法,那么这将不再有效,因为异步运行的方法没有堆栈跟踪,您可以在其中识别它是由ScheduledMethodRunnable或应用程序类触发的。

票数 0
EN

Stack Overflow用户

发布于 2020-12-21 17:41:07

也许你想要实现这样的目标:

代码语言:javascript
复制
@Slf4j
@Component
public class ScheduledTask {

    @Scheduled(cron = "0/1 * * * * *")
    @ScheduledTaskAnnotation(message = "ScheduledTaskMessage", number = 10)
    public void doAction() {
        log.debug("Task scheduled");
    }

}
代码语言:javascript
复制
@Slf4j
@Aspect
@Component
public class ScheduledTaskAspect {

    @Around("execution(public * *(..)) && @annotation(hu.gaszabo.sample.schedule.ScheduledTaskAnnotation)")
    public void logScheduledTaskAction(final ProceedingJoinPoint p) {
        log.debug("Aspect");

        parameters(p).ifPresent(a -> {
            log.debug("message: {}", a.message());
            log.debug("number: {}", a.number());
        });

        try {
            p.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }

    private Optional<ScheduledTaskAnnotation> parameters(final ProceedingJoinPoint p) {
        final Method method = ((MethodSignature) p.getSignature()).getMethod();
        return Optional.ofNullable(AnnotationUtils.findAnnotation(method, ScheduledTaskAnnotation.class));
    }

}
代码语言:javascript
复制
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.METHOD })
public @interface ScheduledTaskAnnotation {

    String message() default "Message";

    long number() default 0L;

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65397019

复制
相关文章

相似问题

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