我们有几项服务需要一段时间才能启动(1-2分钟)。在此过程中,有人可能会请求强制关闭服务(即转换STARTING -> STOPPING
)。查看AbstractService类的来源,我发现在当前状态doStop()
或STARTING
时没有调用NEW
,这意味着当停止请求时不通知基础类收到了。
switch (snapshot.state) {
case NEW:
snapshot = new StateSnapshot(State.TERMINATED);
terminated(State.NEW);
break;
case STARTING:
snapshot = new StateSnapshot(State.STARTING, true, null);
stopping(State.STARTING);
break;
case RUNNING:
snapshot = new StateSnapshot(State.STOPPING);
stopping(State.RUNNING);
doStop();
break;
case STOPPING:
case TERMINATED:
case FAILED:
// do nothing
break;
default:
throw new AssertionError("Unexpected state: " + snapshot.state);
}
由于无论状态如何都需要执行一些清理,是否有办法获得关闭的通知?在子类中使用Service.Listener是个好主意吗?
答案 0 :(得分:4)
状态为doStop
或NEW
时,STARTING
无法呼叫,因为您不必停止从未启动过的服务。这并不意味着在收到停止请求时不会通知基础类。参考the source for stop()
,如果状态为NEW
,则调用terminated
,这会使侦听器排队以调用其terminated
方法。类似地,如果状态为STARTING
,则调用stopping
,这会使侦听器排队以调用其stopping
方法。然后finally
中的stop
阻止调用executeListeners
来执行任何排队Listener
。
简而言之,是的,使用Service.Listener
是个好主意。请务必在启动之前将Listener
添加到Service
,这样您就不会错过任何状态转换的通知。 failed
,stopping
和terminated
方法都会获得Service.State
传递给他们的Service
,因此您可以将清理代码放入正常情况的Listener
terminated
方法(Service
得到RUNNING
的方法),在if (from == STARTING)
方法的stopping
块中您描述了在启动期间强制关闭的位置,以及failed
方法中的特殊情况。