shedlock源码解析

本文主要解析一下shedlock的实现。

LockProvider

shedlock-core-0.16.1-sources.jar!/net/javacrumbs/shedlock/core/LockProvider.java

1
2
3
4
5
6
7
8
复制代码public interface LockProvider {

/**
* @return If empty optional has been returned, lock could not be acquired. The lock
* has to be released by the callee.
*/
Optional<SimpleLock> lock(LockConfiguration lockConfiguration);
}

LockProvider入参是lockConfiguration,返回SimpleLock。

StorageBasedLockProvider

shedlock-core-0.16.1-sources.jar!/net/javacrumbs/shedlock/support/StorageBasedLockProvider.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
复制代码public class StorageBasedLockProvider implements LockProvider {
private final StorageAccessor storageAccessor;
private final LockRecordRegistry lockRecordRegistry = new LockRecordRegistry();

protected StorageBasedLockProvider(StorageAccessor storageAccessor) {
this.storageAccessor = storageAccessor;
}

@Override
public Optional<SimpleLock> lock(LockConfiguration lockConfiguration) {
boolean lockObtained = doLock(lockConfiguration);
if (lockObtained) {
return Optional.of(new StorageLock(lockConfiguration, storageAccessor));
} else {
return Optional.empty();
}
}

/**
* Sets lockUntil according to LockConfiguration if current lockUntil &lt;= now
*/
protected boolean doLock(LockConfiguration lockConfiguration) {
String name = lockConfiguration.getName();

if (!lockRecordRegistry.lockRecordRecentlyCreated(name)) {
// create document in case it does not exist yet
if (storageAccessor.insertRecord(lockConfiguration)) {
lockRecordRegistry.addLockRecord(name);
return true;
}
lockRecordRegistry.addLockRecord(name);
}

return storageAccessor.updateRecord(lockConfiguration);
}

private static class StorageLock implements SimpleLock {
private final LockConfiguration lockConfiguration;
private final StorageAccessor storageAccessor;

StorageLock(LockConfiguration lockConfiguration, StorageAccessor storageAccessor) {
this.lockConfiguration = lockConfiguration;
this.storageAccessor = storageAccessor;
}

@Override
public void unlock() {
storageAccessor.unlock(lockConfiguration);
}
}

}

使用StorageAccessor来实现加锁

LockManager

shedlock-core-0.16.1-sources.jar!/net/javacrumbs/shedlock/core/LockManager.java

1
2
3
4
5
6
复制代码/**
* Executes task if not locked.
*/
public interface LockManager {
void executeWithLock(Runnable task);
}

默认实现
shedlock-core-0.16.1-sources.jar!/net/javacrumbs/shedlock/core/DefaultLockManager.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
复制代码public class DefaultLockManager implements LockManager {
private static final Logger logger = LoggerFactory.getLogger(DefaultLockManager.class);

private final LockingTaskExecutor lockingTaskExecutor;
private final LockConfigurationExtractor lockConfigurationExtractor;

public DefaultLockManager(LockProvider lockProvider, LockConfigurationExtractor lockConfigurationExtractor) {
this(new DefaultLockingTaskExecutor(lockProvider), lockConfigurationExtractor);
}

public DefaultLockManager(LockingTaskExecutor lockingTaskExecutor, LockConfigurationExtractor lockConfigurationExtractor) {
this.lockingTaskExecutor = requireNonNull(lockingTaskExecutor);
this.lockConfigurationExtractor = requireNonNull(lockConfigurationExtractor);
}

@Override
public void executeWithLock(Runnable task) {
Optional<LockConfiguration> lockConfigOptional = lockConfigurationExtractor.getLockConfiguration(task);
if (!lockConfigOptional.isPresent()) {
logger.debug("No lock configuration for {}. Executing without lock.", task);
task.run();
} else {
lockingTaskExecutor.executeWithLock(task, lockConfigOptional.get());
}
}
}

委托给lockingTaskExecutor来加锁
shedlock-core-0.16.1-sources.jar!/net/javacrumbs/shedlock/core/DefaultLockingTaskExecutor.java

1
2
3
> public class DefaultLockingTaskExecutor implements LockingTaskExecutor {  
> private static final Logger logger = LoggerFactory.getLogger(DefaultLockingTaskExecutor.class);
> private final LockProvider lockProvider;

复制代码public DefaultLockingTaskExecutor(LockProvider lockProvider) {
this.lockProvider = requireNonNull(lockProvider);
}

@Override
public void executeWithLock(Runnable task, LockConfiguration lockConfig) {
Optional lock = lockProvider.lock(lockConfig);
if (lock.isPresent()) {
try {
logger.debug(“Locked {}.”, lockConfig.getName());
task.run();
} finally {
lock.get().unlock();
logger.debug(“Unlocked {}.”, lockConfig.getName());
}
} else {
logger.debug(“Not executing {}. It’s locked.”, lockConfig.getName());
}
}

1
}

复制代码>这里跟lockProvider衔接上

SpringLockableTaskSchedulerFactoryBean(偷梁换柱)

shedlock-spring-0.16.1-sources.jar!/net/javacrumbs/shedlock/spring/SpringLockableTaskSchedulerFactoryBean.java

1
2


复制代码@Override
public Class<?> getObjectType() {
return LockableTaskScheduler.class;
}

@Override
protected LockableTaskScheduler createInstance() throws Exception {
return new LockableTaskScheduler(
taskScheduler,
new DefaultLockManager(lockProvider, new SpringLockConfigurationExtractor(defaultLockAtMostFor, defaultLockAtLeastFor, embeddedValueResolver))
);
}

1
2


复制代码>主要是LockableTaskScheduler的工厂方法

LockableTaskScheduler(task scheduler lock wrapper)

shedlock-spring-0.16.1-sources.jar!/net/javacrumbs/shedlock/spring/LockableTaskScheduler.java

1
2
3
public class LockableTaskScheduler implements TaskScheduler, DisposableBean {  
private final TaskScheduler taskScheduler;
private final LockManager lockManager;

复制代码public LockableTaskScheduler(TaskScheduler taskScheduler, LockManager lockManager) {
this.taskScheduler = requireNonNull(taskScheduler);
this.lockManager = requireNonNull(lockManager);
}

@Override
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
return taskScheduler.schedule(wrap(task), trigger);
}

@Override
public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
return taskScheduler.schedule(wrap(task), startTime);
}

@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
return taskScheduler.scheduleAtFixedRate(wrap(task), startTime, period);
}

@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
return taskScheduler.scheduleAtFixedRate(wrap(task), period);
}

@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
return taskScheduler.scheduleWithFixedDelay(wrap(task), startTime, delay);
}

@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
return taskScheduler.scheduleWithFixedDelay(wrap(task), delay);
}

private Runnable wrap(Runnable task) {
return new LockableRunnable(task, lockManager);
}

@Override
public void destroy() throws Exception {
if (taskScheduler instanceof DisposableBean) {
((DisposableBean) taskScheduler).destroy();
}
}

1
}

复制代码>对task scheduler包装了一层,织入了lock的逻辑

问题

上面将了半天,讲了lockProvider以及lockManager,还有LockableTaskScheduler是如何给task scheduler加上锁的,还有LockableTaskScheduler的工厂方法SpringLockableTaskSchedulerFactoryBean。那么问题来了,spring的schedule凭什么就使用你配置的LockableTaskScheduler呢?

1
2
3
4
5
6
7
8
@Bean  
public ScheduledLockConfiguration scheduledLockConfiguration(LockProvider lockProvider) {
return ScheduledLockConfigurationBuilder
.withLockProvider(lockProvider)
.withPoolSize(10)
.withDefaultLockAtMostFor(Duration.ofMinutes(10))
.build();
}

这种配置仅仅当spring工厂里头没有配置taskScheduler的时候,起作用。如果项目已经显示指定taskScheduler的时候,那么就不会使用LockableTaskScheduler。不过可以通过实现SchedulingConfigurer接口强制指定使用LockableTaskScheduler。

doc

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%