開篇
模闆方法模式抽象出某個業務操作公共的流程,将流程分為幾個步驟,其中有一些步驟是固定不變的,有一些步驟是變化的,固定不變的步驟通過一個基類來實作,而變化的部分通過鈎子方法讓子類去實作,這樣就實作了對系統中流程的統一化規範化管理。
Tomcat中關于生命周期管理的地方很好應用了模闆方法模式,在一個元件的生命周期中都會涉及到init(初始化),start(啟動),stop(停止),destory(銷毀),而對于每一個生命周期階段其實都有固定一些事情要做,比如判斷前置狀态,設定後置狀态,以及通知狀态變更事件的監聽者等,而這些工作其實是可以固化的,是以Tomcat中就将每個生命周期階段公共的部分固化,然後通過initInternal,startInternal,stopInternal,destoryInternal這幾個鈎子方法開放給子類去實作具體的邏輯。
源碼分析
說明:
- 1.tomcat的所有容器都實作了Lifecycle的生命周期管理接口,這裡以Tomcat幾個核心元件為例。
- 2.抽象基類LifecycleBase實作Lifecycle接口,在基類當中實作了模闆接口start、stop、init等方法接口。
源碼部分
public interface Lifecycle {
public static final String BEFORE_INIT_EVENT = "before_init";
public static final String AFTER_INIT_EVENT = "after_init";
public static final String START_EVENT = "start";
public static final String BEFORE_START_EVENT = "before_start";
public static final String AFTER_START_EVENT = "after_start";
public static final String STOP_EVENT = "stop";
public static final String BEFORE_STOP_EVENT = "before_stop";
public static final String AFTER_STOP_EVENT = "after_stop";
public static final String AFTER_DESTROY_EVENT = "after_destroy";
public static final String BEFORE_DESTROY_EVENT = "before_destroy";
public static final String PERIODIC_EVENT = "periodic";
public static final String CONFIGURE_START_EVENT = "configure_start";
public static final String CONFIGURE_STOP_EVENT = "configure_stop";
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
public void init() throws LifecycleException;
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
public void destroy() throws LifecycleException;
}
- 1.基類LifecycleBase實作了Lifecycle接口并實作init、start、stop、destroy等方法。
- 2.init()方法内部模闆化初始化流程,抽象具體的實作initInternal()方法。
- 3.start()方法内部模闆化啟動流程,抽象具體的實作startInternal()方法。
- 4.stop()方法内部模闆化停止流程,抽象具體的實作stopInternal()方法。
- 5.destroy()方法内部模闆化釋放流程,抽象具體的實作destroyInternal()方法。
public abstract class LifecycleBase implements Lifecycle {
private static final Log log = LogFactory.getLog(LifecycleBase.class);
private static final StringManager sm = StringManager.getManager(LifecycleBase.class);
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
private volatile LifecycleState state = LifecycleState.NEW;
public void addLifecycleListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
}
public LifecycleListener[] findLifecycleListeners() {
return lifecycleListeners.toArray(new LifecycleListener[0]);
}
public void removeLifecycleListener(LifecycleListener listener) {
lifecycleListeners.remove(listener);
}
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try {
setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.initFail",toString()), t);
}
}
protected abstract void initInternal() throws LifecycleException;
public final synchronized void start() throws LifecycleException {
if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
}
return;
}
if (state.equals(LifecycleState.NEW)) {
init();
} else if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
try {
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
}
}
protected abstract void startInternal() throws LifecycleException;
public final synchronized void stop() throws LifecycleException {
if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) ||
LifecycleState.STOPPED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStopped", toString()));
}
return;
}
if (state.equals(LifecycleState.NEW)) {
state = LifecycleState.STOPPED;
return;
}
if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
}
try {
if (state.equals(LifecycleState.FAILED)) {
fireLifecycleEvent(BEFORE_STOP_EVENT, null);
} else {
setStateInternal(LifecycleState.STOPPING_PREP, null, false);
}
stopInternal();
if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.AFTER_STOP_EVENT);
}
setStateInternal(LifecycleState.STOPPED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.stopFail",toString()), t);
} finally {
if (this instanceof Lifecycle.SingleUse) {
// Complete stop process first
setStateInternal(LifecycleState.STOPPED, null, false);
destroy();
}
}
}
protected abstract void stopInternal() throws LifecycleException;
@Override
public final synchronized void destroy() throws LifecycleException {
if (LifecycleState.FAILED.equals(state)) {
try {
// Triggers clean-up
stop();
} catch (LifecycleException e) {
// Just log. Still want to destroy.
log.warn(sm.getString(
"lifecycleBase.destroyStopFail", toString()), e);
}
}
if (LifecycleState.DESTROYING.equals(state) ||
LifecycleState.DESTROYED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e);
} else if (log.isInfoEnabled() && !(this instanceof Lifecycle.SingleUse)) {
log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString()));
}
return;
}
if (!state.equals(LifecycleState.STOPPED) &&
!state.equals(LifecycleState.FAILED) &&
!state.equals(LifecycleState.NEW) &&
!state.equals(LifecycleState.INITIALIZED)) {
invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT);
}
try {
setStateInternal(LifecycleState.DESTROYING, null, false);
destroyInternal();
setStateInternal(LifecycleState.DESTROYED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.destroyFail",toString()), t);
}
}
protected abstract void destroyInternal() throws LifecycleException;
}
招聘資訊
【招賢納士】
歡迎熱愛技術、熱愛生活的你和我成為同僚,和貝貝共同成長。
貝貝集團誠招算法、大資料、BI、Java、PHP、android、iOS、測試、運維、DBA等人才,有意可投遞
[email protected]。
貝貝集團建立于2011年,旗下擁有貝貝網、貝店、貝貸等平台,緻力于成為全球領先的家庭消費平台。
貝貝創始團隊來自阿裡巴巴,先後獲得IDG資本、高榕資本、今日資本、新天域資本、北極光等數億美金的風險投資。
公司位址:杭州市江幹區普盛巷9号東谷創業園(上下班有多趟班車)