前言,我在测试使用Shedlock时,使用的是Redis作为其存储库,因此本篇也是以Redis分布式锁来描述的。
准备程序引入依赖
net.javacrumbs.shedlock shedlock-spring4.0.4 net.javacrumbs.shedlock shedlock-provider-redis-spring2.5.0
创建一个定时任务
@Scheduled(cron = "0/10 * * * * ?") // 每天17点执行
@SchedulerLock(name = "heartbeat",
lockAtLeastFor = "10s",
lockAtMostFor = "10s")
public void heartbeat() {
DateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
log.info(dateFormat.format(new Date()));
}
分析程序
首先我们先找到程序的入口,通过注解实现额外功能,显然是用到了代理模式,所以我们来看Shedlock的源码:(可以通过点击找到注解的调用处,就能跳转到Advisor方法)
MethodProxyScheduledLockAdvisor打开此类看到的是通过 AbstractPointcutAdvisor 实现的一个切面,然后通过MethodInterceptor实现方法的环绕执行:(此处其实是用到了设计模式中的命令模式,将要执行的方法进行了传递,传递业务并不需要了解方法的具体执行细节)
1. 首先通过注解拿到相关配置,比如锁名称,锁过期时间
2. 将方法传递给执行器执行
LockingTaskExecutor通过本地线程变量来存储线程获取的锁,实现线程锁的可重入操作;
RedisLockProviderRedis底层所使用到的命令其实就是```set key value ex nx```语法来实现的;
总结在成熟的框架源码中其实是使用到了大量的设计模式,像本框架中,就使用到了包括代理,命令,模板方法模式和策略模式;源码还是很有必要阅读的。



