当前位置:网站首页>@Scheduled注解的坑,我替你踩了
@Scheduled注解的坑,我替你踩了
2022-06-29 23:28:00 【InfoQ】
问题背景
Spring@ScheduledSpring@Scheduled@Scheduled失效原因分析
@ScheduledSpringBoot@Scheduled@Scheduled
Spring@Scheduled
ScheduledAnnotationBeanPostProcessor@ScheduledBeanPostProcessorSpringbeanbeforeafterbeanSpringBeanPostProcessorpostProcessAfterInitializationbeanSpringBootScheduledAnnotationBeanPostProcessor
ScheduledAnnotationBeanPostProcessorpublic class ScheduledAnnotationBeanPostProcessor implements MergedBeanDefinitionPostProcessor, DestructionAwareBeanPostProcessor, Ordered, EmbeddedValueResolverAware, BeanNameAware, BeanFactoryAware, ApplicationContextAware, SmartInitializingSingleton, ApplicationListener<ContextRefreshedEvent>, DisposableBean {
...
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof AopInfrastructureBean) {
return bean;
} else {
//(key-1)解析所有Scheduled注解的类
Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
if (!this.nonAnnotatedClasses.contains(targetClass)) {
Map<Method, Set<Scheduled>> annotatedMethods = MethodIntrospector.selectMethods(targetClass, new MetadataLookup<Set<Scheduled>>() {
public Set<Scheduled> inspect(Method method) {
Set<Scheduled> scheduledMethods = AnnotatedElementUtils.getMergedRepeatableAnnotations(method, Scheduled.class, Schedules.class);
return !scheduledMethods.isEmpty() ? scheduledMethods : null;
}
});
if (annotatedMethods.isEmpty()) {
this.nonAnnotatedClasses.add(targetClass);
if (this.logger.isTraceEnabled()) {
this.logger.trace("No @Scheduled annotations found on bean class: " + targetClass);
}
} else {
Iterator var5 = annotatedMethods.entrySet().iterator();
while(var5.hasNext()) {
Entry<Method, Set<Scheduled>> entry = (Entry)var5.next();
Method method = (Method)entry.getKey();
Iterator var8 = ((Set)entry.getValue()).iterator();
while(var8.hasNext()) {
Scheduled scheduled = (Scheduled)var8.next();
//(key-2)处理被注解修饰的类
this.processScheduled(scheduled, method, bean);
}
}
if (this.logger.isDebugEnabled()) {
this.logger.debug(annotatedMethods.size() + " @Scheduled methods processed on bean '" + beanName + "': " + annotatedMethods);
}
}
}
return bean;
}
}
...
}
@Scheduled@Schedulesmapkey@Scheduled@Scheduleskey-1``mapprocessScheduledprotected void processScheduled(Scheduled scheduled, Method method, Object bean) {
try {
Runnable runnable = this.createRunnable(bean, method);
boolean processedSchedule = false;
String errorMessage = "Exactly one of the 'cron', 'fixedDelay(String)', or 'fixedRate(String)' attributes is required";
Set<ScheduledTask> tasks = new LinkedHashSet(4);
long initialDelay = scheduled.initialDelay();
...
//(key-1)获取注解中对应的scron参数
String cron = scheduled.cron();
if (StringUtils.hasText(cron)) {
String zone = scheduled.zone();
if (this.embeddedValueResolver != null) {
cron = this.embeddedValueResolver.resolveStringValue(cron);
zone = this.embeddedValueResolver.resolveStringValue(zone);
}
if (StringUtils.hasLength(cron)) {
Assert.isTrue(initialDelay == -1L, "'initialDelay' not supported for cron triggers");
processedSchedule = true;
if (!"-".equals(cron)) {
TimeZone timeZone;
if (StringUtils.hasText(zone)) {
timeZone = StringUtils.parseTimeZoneString(zone);
} else {
timeZone = TimeZone.getDefault();
}
//(key-2)添加到任务列表
tasks.add(this.registrar.scheduleCronTask(new CronTask(runnable, new CronTrigger(cron, timeZone))));
}
}
}
...
Assert.isTrue(processedSchedule, errorMessage);
Map var18 = this.scheduledTasks;
synchronized(this.scheduledTasks) {
Set<ScheduledTask> regTasks = (Set)this.scheduledTasks.computeIfAbsent(bean, (key) -> {
return new LinkedHashSet(4);
});
regTasks.addAll(tasks);
}
} catch (IllegalArgumentException var25) {
throw new IllegalStateException("Encountered invalid @Scheduled method '" + method.getName() + "': " + var25.getMessage());
}
}
CronTask
springboot
public ScheduledTask scheduleCronTask(CronTask task) {
ScheduledTask scheduledTask = this.unresolvedTasks.remove(task);
boolean newTask = false;
if (scheduledTask == null) {
scheduledTask = new ScheduledTask();
newTask = true;
}
if (this.taskScheduler != null) {
scheduledTask.future = this.taskScheduler.schedule(task.getRunnable(), task.getTrigger());
}
else {
addCronTask(task);
this.unresolvedTasks.put(task, scheduledTask);
}
return (newTask ? scheduledTask : null);
}JVMJVMCPU ticksSpringSpring
public ScheduledFuture<?> schedule() {
synchronized (this.triggerContextMonitor) {
this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
if (this.scheduledExecutionTime == null) {
return null;
}
//获取时间差
long initialDelay = this.scheduledExecutionTime.getTime() - System.currentTimeMillis();
this.currentFuture = this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);
return this;
}
}
@ScheduledScheduledThreadPoolExecutorSystem.nanoTime边栏推荐
- How can the local / park do a good job in industrial analysis?
- Pytest initializing and cleaning up the environment
- C pointer advanced 2-- > function pointer array callback function simplifies calculator code, and implements qsort function based on callback function simulation
- 开源了 | 文心大模型ERNIE-Tiny轻量化技术,又准又快,效果全开
- 收藏!这些提高程序员生产力的工具你用过吗?
- Solr基础操作4
- Redis client
- Regular expressions: characters (2)
- 剑指 Offer 14- II. 剪绳子 II
- 剑指 Offer 38. 字符串的排列
猜你喜欢

2022 PMP project management examination agile knowledge points (5)

Leetcode 1385. 两个数组间的距离值

Leetcode(76)——最小覆盖子串

Software testing interface testing postman testing tool interface testing process execution interface testing interface associated environment variables and global variables built-in dynamic parameter

二叉搜索树 230. 二叉搜索树中第K小的元素 1038. 从二叉搜索树到更大和树

redis客户端

按头安利!好看又实用的电机 SolidWorks模型素材看这里

matlab习题 —— 程序控制流程练习

Procurement intelligence is about to break out, and the "3+2" system of Alipay helps enterprises build core competitive advantages

C指针进阶2-->函数指针数组 回调函数简化计算器代码,基于回调函数模拟实现qsort函数
随机推荐
RRDTOOL draws MRTG log data
Head pressing Amway good-looking and practical dispensing machine SolidWorks model material here
Solr basic operation 5
Is it safe to open a stock account? Shanghai stock account opening.
Top ten securities companies: "bulldozer market" reappearance
Open source the Ernie tiny lightweight technology of "Wenxin big model", which is accurate and fast, with full effect
PROJECT #1 - BUFFER POOL [CMU 15-445645]笔记
新钛云服荣膺“2022爱分析 · IT运维厂商全景报告”云管理平台CMP 代表厂商!...
简单理解B树和B+树
Matplotlib histogram of Matplotlib visualization plt bar()
Speech signal processing (II): phonation physiology, auditory physiology and auditory psychology
Test d'installation du cluster metaq
111. simple chat room 14: chat room client
Implementation principle of dynamic agent
Matplotlib plt Hist() parameter explanation
Wechat applet: big red festive UI guessing lantern riddles is also called guessing character riddles
[learn FPGA programming from scratch -51]: high level chapter - FPGA development based on IP core - what is FPGA IP core (soft core, fixed core, hard core) and learning methods
Pytest initializing and cleaning up the environment
Gracefully transform the SMS business module and start the strategic mode!
Solr基础操作4