摘自:https://www.jianshu.com/p/8def04b34b3cjava
首先,了解状态机是什么,咱们为何须要状态机!
举个最简单例子,请假,做为一个最底层程序员,每次请假都要领导层层审批,而假有分为不少种,事假,病假,婚假,年休假等等,固然选择请的假不一样,审批标准也不一样,不一样的假单须要走的审批链也不同,好比年休假,可能只须要领导审批扣掉年休假便可,请病假须要领导审批,领导审批以后,先休假,等休完假回来提交病假的材料,由hr审批以后才能完成整个请假过程。更有甚者,若是你要修一个一个月的长假,就不只仅是须要直线领导hr审批,可能还须要公司ceo审批 ,审批经过后,才能经过。以下图:git
public void requestLeavePermit(String type){ if(type.equals("事假")){ //领导审批->hr审批->ceo审批->完成 }else if(type.equals("病假")){ //领导审批->休假->补充病例->hr审批->完成 }else if(type.equals("年休假")){ //领导审批->hr审批->经过 }else if(type.equals("产假")){ //领导审批->hr审批->经过 }else if(type.equals("调休假")){ //领导审批->ceo审批->经过 } }
或者写成这个样子:程序员
public void requestLeavePermit(String type,String userName){ switch (type){ case "事假": //领导审批->hr审批->ceo审批->完成 break; case "病假": //领导审批->休假->补充病例->hr审批->完成 break; case "年休假": //领导审批->hr审批->经过 break; case "产假": //领导审批->hr审批->经过 break; case "调休假": //领导审批->ceo审批->经过 default: break; } }
public enum LeavePermitEnum { ANNUAL_LEAVE("annual_leave","年休假 "), CASUAL_LEAVE("casual_leave","事假"), MEDICAL_LEAVE("medical_leave","病假"), MARRIAGE_LEAVE("marriage_leave","婚假"),; private String type; private String memo; //此处忽略构造方法和set/get方法 }
领导审批,hr审批,ceo审批,都有一个审批意见(经过,拒绝,或者是重修修改假单补充材料等),在这里,至关于一个事件Event,因而,整个状态扭转也能够用一个枚举类来表示,审批意见由一个枚举类Event来表示。github
public enum Event { AGREE("agree","赞成"), DISSAGREE("disagree","不一样意"), MODIFY("modify","修改"), ; private String type; private String memo; }
所以,一个假单的状态就有不少种,用一个枚举表明整个假单的状态:ide
public enum Status { //提交假单 PERMIT_SUBMIT("permitSubmit","提交假单"), //领导审批 LEADER_PERMITING("leaderPermiting","领导审批中"), LEADER_PERMIT_AGREE("leaderAgree","领导赞成"), LEADER_PERMIT_DISAGREE("leaderDisAgree","领导不一样意"), LEADER_PERMIT_MODIFY("leaderModify","领导以为须要补充材料重修修改"), //hr审批 HR_PERMITING("hrPermiting","hr审批中"), HR_PERMIT_AGREE("hrAgree","hr赞成"), HR_PERMIT_DISAGREE("hrDisAgree","hr不一样意"), HR_PERMIT_MODIFY("hrModify","hr以为须要补充材料重修修改"), //ceo审批 CEO_PERMITING("ceoPermiting","领导审批中"), CEO_PERMIT_AGREE("ceoAgree","ceo赞成"), CEO_PERMIT_DISAGREE("ceoDisAgree","ceo不一样意"), CEO_PERMIT_MODIFY("ceoModify","ceo以为须要补充材料重修修改"), //最终请假状态 PERMIT_SUCCESS("permitSuccess","请假成功"), PERMIT_FAIL("permitFail","请假失败") ; private String status; private String memo; private Status(String status,String memo){ this.status=status; this.memo=memo; } }
状态定义清楚以后,须要考虑两个问题post
这块功能能够交给状态机StatusMachine去解决,由当前状态+事件驱动(也就是当前请假的状态和审批意见)获取下一个状态。ui
咱们知道,请假的种类不一样,所走的流程也不一样,相应的处理也不一样,每种假单都有本身的审批链,也对应每种假单有不一样的状态机,不难设计StatusMachine为接口或抽象类。状态机只作一件事情,根据event(审批意见),跳转下一个状态机。this
public interface StatusMachine { /** *@params status 当前状态 *@params event 审批意见 *@return 下一个状态 **/ public Status getNextStatus(Status status,Event event); }
这里举两个例子,一个病假,一个年休假的实现:设计
年休假的审批流程:code
所以事假的状态机StatusMachine实现以下:
public class AnnualLeaveStatusMachine implements StatusMachine{ public Status getNextStatus(Status status,Event event){ switch (status){ case PERMIT_SUBMIT: //提交假单状态无需审批跳转领导审批中状态 return Status.LEADER_PERMITING; case LEADER_PERMITING: //领导审批须要审批意见 审批意见不用返回不一样的状态 return getLeaderPermitStatus(event); case LEADER_PERMIT_AGREE: //领导赞成请假,则跳转ceo审批 return Status.CEO_PERMITING; case LEADER_PERMIT_DISAGREE: //领导不一样意该假单,则请假失败 return Status.PERMIT_FAIL; case LEADER_PERMIT_MODIFY: return getLeaderPermitStatus(event); case CEO_PERMITING: //ceo审批须要审批意见 return getCEOPermitStatus(event); case CEO_PERMIT_AGREE: // ceo审批赞成 跳转审批经过 请假完成 return Status.PERMIT_SUCCESS; case CEO_PERMIT_DISAGREE: //ceo不一样意审批 则跳转审批失败 return Status.PERMIT_FAIL; case CEO_PERMIT_MODIFY: return getCEOPermitStatus(event); default: throw new RuntimeException("没有该流程"); } } private Status getLeaderPermitStatus(Event event){ switch (event){ case AGREE: //领导审批经过 返回赞成该假单 return Status.LEADER_PERMIT_AGREE; case DISSAGREE: //领导不一样意 则返回领导拒绝改假单状态 return Status.LEADER_PERMIT_DISAGREE; case MODIFY: return Status.LEADER_PERMIT_MODIFY; default: throw new RuntimeException("不支持该Event审批意见"); } } private Status getCEOPermitStatus(Event event){ switch (event){ case AGREE: //ceo审批经过 则返回ceo赞成该假单 return Status.CEO_PERMIT_AGREE; case DISSAGREE: // ceo审批不经过 则返回ceo不一样意该假单状态 return Status.CEO_PERMIT_DISAGREE; case MODIFY: return Status.CEO_PERMIT_MODIFY; default: throw new RuntimeException("不支持该Event审批意见"); } } }
病假的审批流程:
public class MedicalLeaveStatusMachine implements StatusMachine{ public Status getNextStatus(Status status,Event event){ switch (status){ case PERMIT_SUBMIT: //提交假单状态直接跳转领导审批中状态 return Status.LEADER_PERMITING; case LEADER_PERMITING: //领导审批中状态须要审批意见再获取下一个状态 return getLeaderPermitStatus(event); case LEADER_PERMIT_AGREE: //领导赞成审批该假单 跳转hr审批中状态 return Status.HR_PERMITING; case LEADER_PERMIT_DISAGREE: //领导不一样意则返回请假失败 return Status.PERMIT_FAIL; case LEADER_PERMIT_MODIFY: return getLeaderPermitStatus(event); case HR_PERMITING: //hr审批根据审批意见跳转下一个状态 return getHrPermitStatus(event); case HR_PERMIT_AGREE: //hr审批经过跳转审批完成状态 return Status.PERMIT_SUCCESS; case HR_PERMIT_DISAGREE: // hr审批不一样意 返回请假失败 return Status.PERMIT_FAIL; case HR_PERMIT_MODIFY: return getHrPermitStatus(event); default: throw new RuntimeException("没有该流程"); } } private Status getLeaderPermitStatus(Event event){ switch (event){ case AGREE: //领导赞成该假单,则返回领导审批经过 return Status.LEADER_PERMIT_AGREE; case DISSAGREE: //领导不一样意该假单 则返回领导审批不经过 return Status.LEADER_PERMIT_DISAGREE; case MODIFY: return Status.LEADER_PERMIT_MODIFY; default: throw new RuntimeException("不支持该Event审批意见"); } } private Status getHrPermitStatus(Event event){ switch (event){ case AGREE: //hr审批赞成该假单,则返回hr赞成状态 return Status.HR_PERMIT_AGREE; case DISSAGREE: //hr审批不一样意该假单,则返回hr不一样意状态 return Status.HR_PERMIT_DISAGREE; case MODIFY: return Status.HR_PERMIT_MODIFY; default: throw new RuntimeException("不支持该Event审批意见"); } } }
对于请假的员工来说,只知道提交了一个假单,并不会关心到底该流程怎么走,因此在设计的时候,须要根据请假类型可以自动匹配状态机,这里能够用静态工厂去实现。
public class StatusMachineFactory { private StatusMachineFactory(){ } /** * 根据状态获取状态机 * @param leavePermitType * @return 对应请假类型的状态机 */ public static StatusMachine getStatusMachine(LeavePermitType leavePermitType){ switch (leavePermitType){ case MEDICAL_LEAVE: return new MedicalLeaveStatusMachine(); case ANNUAL_LEAVE: return new AnnualLeaveStatusMachine(); default: throw new RuntimeException("未知类型"); } } }
状态机设计好以后,每一个状态都应该对应有该状态的处理类,且须要统一管理该状态和处理类的关系。
以年休假为例:提交假单->领导审批4个状态->ceo审批4个状态->请假完成/失败2个状态。
总计须要11个状态处理对象去处理该状态。
该状态处理类须要具有哪些能力:
不难设计,先抽象出一个StatusHandler接口或父类,每一个状态的处理类去实现该接口或继承该父类,在statusHandler中,有三个方法,before,dohandler,after,after主要负责扭转状态机,获取下一个状态的处理类处理下一个状态的事件。若是状态到达某一个状态不须要往下继续执行,则重写after方法便可中断状态机,dohandler主要负责作业务处理。
public interface AbstractStatusHandler { public void handle(LeavePermit leavePermit); } public abstract class StatusHandler implements AbstractStatusHandler{ protected void before(LeavePermit leavePermit){ } public void handle(LeavePermit leavePermit){ before(leavePermit); doHandler(leavePermit); after(leavePermit); } protected abstract void doHandler(LeavePermit leavePermit); protected void after(LeavePermit leavePermit){ //去下一个状态的处理对象处理 goNextStatusHandler(leavePermit); } protected void goNextStatusHandler(LeavePermit leavePermit){ //获取下一个状态 leavePermit.setStatus(StatusMachineFactory.getStatusMachine(leavePermit.getLeavePermitType()).getNextStatus(leavePermit.getStatus(),leavePermit.getEvent())); //状态机引擎驱动假单处理 StatusMachineEngine.post(leavePermit); }
在看一下具体的状态处理类实现,11个状态对应11个处理类,这里列举出部分
public class AnnualPermitSubmitStatusHandler extends StatusHandler{ protected void doHandler(LeavePermit leavePermit){ System.out.println(String.format("user:%s--提交年休假假单--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus())); } } public class AnnualLeaderPermitingStatusHandler extends StatusHandler{ protected void doHandler(LeavePermit leavePermit){ System.out.println(String.format("user:%s--领导审批年休假中--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus())); } @Override protected void after(LeavePermit leavePermit){ if(leavePermit.getEvent()==null){ //还未审批,状态机结束,等待审批意见 System.out.println(String.format("user:%s--等待领导审批--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus())); return; } super.goNextStatusHandler(leavePermit); } } public class AnnualLeaderAgreeStatusHandler extends StatusHandler{ protected void doHandler(LeavePermit leavePermit){ System.out.println(String.format("user:%s--直线领导赞成请年休假--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus())); } } public class AnnualLeaderAgreeStatusHandler extends StatusHandler{ protected void doHandler(LeavePermit leavePermit){ leavePermit.setEvent(null); System.out.println(String.format("user:%s--直线领导赞成请年休假--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus())); } } public class AnnualCEOPermitingStatusHandler extends StatusHandler{ protected void doHandler(LeavePermit leavePermit){ System.out.println(String.format("user:%s--ceo审批年休假中--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus())); } protected void after(LeavePermit leavePermit){ if(leavePermit.getEvent()==null){ //还未审批,状态机结束,等待审批意见 System.out.println(String.format("user:%s--等待ceo审批--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus())); return; } goNextStatusHandler(leavePermit); } } public class AnnualCEOAgreeStatusHandler extends StatusHandler{ protected void doHandler(LeavePermit leavePermit){ System.out.println(String.format("user:%s--ceo赞成休年休假--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus())); } } public class AnnualPermitSuccessStatusHandler extends StatusHandler{ @Override protected void doHandler(LeavePermit leavePermit){ System.out.println(String.format("user:%s--请年休假假成功--leavePermit status:%s",leavePermit.getUser(),leavePermit.getStatus().getStatus(),leavePermit.getStatus().getMemo())); } @Override protected void after(LeavePermit leavePermit){ } }
关于假单的请求,都会由StatusMachineEngine.post(LeavePermit)去处理,这里是如何作到按照请假类型,和状态找到对应的statusHandler的?
这里是使用eventbus去实现(基于消息订阅发布模式实现)
public class StatusMachineEngine { private static EventBus eventBus; static{ eventBus = new EventBus(); } /** * 发布一条假单 * @param leavePermit */ public static void post(LeavePermit leavePermit) { eventBus.post(leavePermit); } /** * 假单处理类 * @param statusLeavePermitHandler */ public static void addListener(LeavePermitHandler statusLeavePermitHandler) { eventBus.register(statusLeavePermitHandler); } }
全部假单的处理都会交给LeavePermitHandler去处理,这个对象里按照请假类型和请假状态作路由,选择不一样的statusHandler处理业务逻辑。
public class LeavePermitHandler { //处理假单 注解表明能够接受到StatusMachineEngine发布的假单 @Subscribe @AllowConcurrentEvents public void handle(LeavePermit leavePermit){ //获取到状态处理类,而后去处理 handler为StatusHandler的入口 getStatusHandler(leavePermit).handle(leavePermit); } /** * 根据假单获取StatusHandler 状态处理对象 * @param leavePermit * @return */ public static StatusHandler getStatusHandler(LeavePermit leavePermit){ return StatusHandlerRegistry.acquireStatusHandler(leavePermit.getLeavePermitType(),leavePermit.getStatus()); } }
全部的状态处理类都会保存在StatusHandlerRegistry对象中,该对象负责注册全部有关请假类型,状态和状态处理类的关系,每次都根据请假类型和状态去获取StatusHandler。
public class StatusHandlerRegistry { private static Map<String,StatusHandler> statusHandlerMap; static { statusHandlerMap=new ConcurrentHashMap<String, StatusHandler>(); } private StatusHandlerRegistry(){ } private static String getKey(LeavePermitType leavePermitType,Status status){ return String.format("%s@-@%s",leavePermitType.getType(),status.name()); } /** * 注册状态处理类 * @param leavePermitType 请假类型 * @param status 请假状态 * @param statusHandler 状态处理对象 */ public static void registryStatusHandler(LeavePermitType leavePermitType,Status status,StatusHandler statusHandler){ statusHandlerMap.put(getKey(leavePermitType,status),statusHandler); } /** * 获取状态处理类 * @param leavePermitType 请假类型 * @param status 请假状态 * @return StatusHandler */ public static StatusHandler acquireStatusHandler(LeavePermitType leavePermitType,Status status){ return statusHandlerMap.get(getKey(leavePermitType,status)); } }
public static void main(String[] args) { //注册年休假的状态和对应状态的处理类StatusHandler。 registryAnnualPermitStatusHandler(); //注册病假的状态和对应状态的处理类StatusHandler。 registryMedicalPermitStatusHandler(); LeavePermitHandler leavePermitHandler=new LeavePermitHandler(); //状态机引擎接受事件处理类 StatusMachineEngine.addListener(leavePermitHandler); //生成假单 LeavePermit leavePermit=new LeavePermit(); leavePermit.setLeavePermitType(LeavePermitType.ANNUAL_LEAVE); leavePermit.setStatus(Status.PERMIT_SUBMIT); leavePermit.setUser("jettyrun"); //假单交给引擎去执行 StatusMachineEngine.post(leavePermit); System.out.println("----- 分割线 表明假条须要领导审批了,领导给个经过意见,而后状态机接着走-------"); leavePermit.setEvent(Event.AGREE); StatusMachineEngine.post(leavePermit); System.out.println("----- 分割线 表明假条须要ceo审批了,ceo给个经过意见,而后状态机接着走-------"); leavePermit.setEvent(Event.AGREE); StatusMachineEngine.post(leavePermit); System.out.println("--->>>>>>>>>end<<<<<<<<-------"); } public static void registryAnnualPermitStatusHandler() { StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.PERMIT_SUBMIT, new AnnualPermitSubmitStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.LEADER_PERMIT_AGREE, new AnnualLeaderAgreeStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.LEADER_PERMIT_DISAGREE, new AnnualLeaderDisAgreeStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.LEADER_PERMIT_MODIFY, new AnnualLeaderPermitModifyStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.LEADER_PERMITING, new AnnualLeaderPermitingStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.CEO_PERMIT_AGREE, new AnnualCEOAgreeStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.CEO_PERMIT_DISAGREE, new AnnualCEODisAgreeStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.CEO_PERMIT_MODIFY, new AnnualCEOPermitModifyStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.CEO_PERMITING, new AnnualCEOPermitingStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.PERMIT_SUCCESS, new AnnualPermitSuccessStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.ANNUAL_LEAVE, Status.PERMIT_FAIL, new AnnualPermitFailStatusHandler()); } public static void registryMedicalPermitStatusHandler() { StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.PERMIT_SUBMIT, new MedicalPermitSubmitStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.LEADER_PERMIT_AGREE, new MedicalLeaderAgreeStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.LEADER_PERMIT_DISAGREE, new MedicalLeaderDisAgreeStatusHandler ()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.LEADER_PERMIT_MODIFY, new MedicalLeaderPermitModifyStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.LEADER_PERMITING, new MedicalLeaderPermitingStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.HR_PERMIT_AGREE, new MedicalHrAgreeStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.HR_PERMIT_DISAGREE, new MedicalHrDisAgreeStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.HR_PERMIT_MODIFY, new MedicalHrPermitModifyStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.HR_PERMITING, new MedicalHrPermitingStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.PERMIT_SUCCESS, new MedicalPermitSuccessStatusHandler()); StatusHandlerRegistry.registryStatusHandler(LeavePermitType.MEDICAL_LEAVE, Status.PERMIT_FAIL, new MedicalPermitFailStatusHandler()); }
执行结果:
user:jettyrun--提交年休假假单--leavePermit status:permitSubmit user:jettyrun--领导审批年休假中--leavePermit status:leaderPermiting user:jettyrun--等待领导审批--leavePermit status:leaderPermiting ----- 分割线 表明假条须要领导审批了,领导给个经过意见,而后状态机接着走------- user:jettyrun--领导审批年休假中--leavePermit status:leaderPermiting user:jettyrun--直线领导赞成请年休假--leavePermit status:leaderAgree user:jettyrun--ceo审批年休假中--leavePermit status:ceoPermiting user:jettyrun--等待ceo审批--leavePermit status:ceoPermiting ----- 分割线 表明假条须要领导审批了,ceo给个经过意见,而后状态机接着走------- user:jettyrun--ceo审批年休假中--leavePermit status:ceoPermiting user:jettyrun--ceo赞成休年休假--leavePermit status:ceoAgree user:jettyrun--请年休假假成功--leavePermit status:permitSuccess --->>>>>>>>>end<<<<<<<<-------
能够看到,当须要领导,CEO审批假单的时候,状态机可以自动中断,领导,ceo赞成了该请假请求leavePermit.setEvent(Event.AGREE);状态机就可以自动运行到最终状态permitSuccess。
LeavePermit leavePermit2=new LeavePermit(); leavePermit2.setLeavePermitType(LeavePermitType.MEDICAL_LEAVE); leavePermit2.setStatus(Status.PERMIT_SUBMIT); leavePermit2.setUser("jettyrun2"); StatusMachineEngine.post(leavePermit2); System.out.println("----- 分割线 表明假条须要领导审批了,领导给个经过意见,而后状态机接着走-------"); leavePermit2.setEvent(Event.AGREE); StatusMachineEngine.post(leavePermit2); System.out.println("----- 分割线 表明假条须要hr审批了,hr给个经过意见,而后状态机接着走-------"); leavePermit2.setEvent(Event.AGREE); StatusMachineEngine.post(leavePermit2); System.out.println("--->>>>>>>>>end<<<<<<<<-------");
user:jettyrun2--病假提交--leavePermit status:permitSubmit-提交假单 user:jettyrun2--领导审批病假中--leavePermit status:leaderPermiting-领导审批中 user:jettyrun2--等待领导病假审批--leavePermit status:leaderPermiting-领导审批中 ----- 分割线 表明假条须要领导审批了,领导给个经过意见,而后状态机接着走------- user:jettyrun2--领导审批病假中--leavePermit status:leaderPermiting-领导审批中 user:jettyrun2--领导赞成休病假--leavePermit status:leaderAgree-领导赞成 user:jettyrun2--hr审批病假中--leavePermit status:hrPermiting-hr审批中 user:jettyrun2--等待hr审批--leavePermit status:hrPermiting ----- 分割线 表明假条须要hr审批了,hr给个经过意见,而后状态机接着走------- user:jettyrun2--hr审批病假中--leavePermit status:hrPermiting-hr审批中 user:jettyrun2--hr赞成休病假--leavePermit status:hrAgree-hr赞成 user:jettyrun2--成功病假审批--leavePermit status:permitSuccess-请假成功 --->>>>>>>>>end<<<<<<<<-------
该状态机的设计思想有一部分借鉴公司的几个项目,一部分来源于当当elastic-job的源码解读心得。
源代码地址请点击我 github