shedlock-core-0.16.1-sources.jar!/net/javacrumbs/shedlock/core/LockProvider.java
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。
shedlock-core-0.16.1-sources.jar!/net/javacrumbs/shedlock/support/StorageBasedLockProvider.java
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 <= 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来实现加锁
shedlock-core-0.16.1-sources.jar!/net/javacrumbs/shedlock/core/LockManager.java
/** * 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
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
```
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<SimpleLock> 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()); } }
}
>这里跟lockProvider衔接上 ## SpringLockableTaskSchedulerFactoryBean(`偷梁换柱`) shedlock-spring-0.16.1-sources.jar!/net/javacrumbs/shedlock/spring/SpringLockableTaskSchedulerFactoryBean.java
@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)) ); }
>主要是LockableTaskScheduler的工厂方法 ### LockableTaskScheduler(`task scheduler lock wrapper`) shedlock-spring-0.16.1-sources.jar!/net/javacrumbs/shedlock/spring/LockableTaskScheduler.java
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(); } }
}
>对task scheduler包装了一层,织入了lock的逻辑 ## 问题 上面将了半天,讲了lockProvider以及lockManager,还有LockableTaskScheduler是如何给task scheduler加上锁的,还有LockableTaskScheduler的工厂方法SpringLockableTaskSchedulerFactoryBean。那么问题来了,spring的schedule凭什么就使用你配置的LockableTaskScheduler呢?
@Bean
public ScheduledLockConfiguration scheduledLockConfiguration(LockProvider lockProvider) {
return ScheduledLockConfigurationBuilder
.withLockProvider(lockProvider)
.withPoolSize(10)
.withDefaultLockAtMostFor(Duration.ofMinutes(10))
.build();
}
```
这种配置仅仅当spring工厂里头没有配置taskScheduler的时候,起作用。如果项目已经显示指定taskScheduler的时候,那么就不会使用LockableTaskScheduler。不过可以通过实现SchedulingConfigurer接口强制指定使用LockableTaskScheduler。