자바 생명주기 관리 메커니즘 실현
최근 한 국산 오픈 소스 인 MySQL 데이터베이스 미들웨어 를 연구 해 최신 버 전의 코드 를 eclipse 까지 끌 어 내 린 뒤 시작 해 각종 테스트 와 코드 추적 을 하고 있다.사용 하고 닫 으 려 고 할 때 STOP 클래스 를 끌 어 내 서 실행 하려 고 할 때 이 클래스 에 갑자기 다음 몇 줄 의 코드 만 쓰 여 있 는 것 을 발견 하고 나 는 순간 많은 상 처 를 받 았 다 고 느 꼈 다.
public static void main(String[] args) {
System.out.println(new Date() + ",server shutdown!");
}
이 미들웨어 가 시작 되 고 실 행 될 때 감청 이 켜 져 많은 스 레 드 가 달리 고 있 으 며 많은 socket 연결 이 되 어 있 습 니 다.하지만 우아 하 게 닫 을 수 있 는 방법 은 찾 지 못 했다.그래서 어 쩔 수 없 이 나 는 eclipse 의 가슴 이 찢 어 지 는 빨 간 점 을 누 르 고 VM 을 강제로 멈 출 수 밖 에 없 었 다.
만약 에 구조 가 양호 하고 모듈 화 된 뚜렷 한 소프트웨어,특히 서버 류 의 소프트웨어 라면 생명주기 관리 메커니즘 을 갖 추 는 것 이 매우 중요 하 다.각 모듈 의 생명 주 기 를 관리 할 수 있 을 뿐만 아니 라 전체 소프트웨어 를 시작 할 때 더욱 우아 하고 어떠한 자원 도 빠 뜨리 지 않 을 수 있다.
생명주기 메커니즘 간이 실현
생명주기 상태
한 모듈 의 생명주기 상 태 는 일반적으로 다음 과 같은 몇 가지 가 있다.
신입생->초기 화 중->초기 화 완료->시작 중->시작 완료->일시 정지 중->일시 정지 중->복구 중->복구 중->소각 중->소각 중
그 중에서 어떤 상태 간 의 전환 이 실패 하면 다른 상태 로 들어간다.실패.
이 를 위해 하나의 매 거 류 로 이 몇 가지 상 태 를 들 수 있 습 니 다.다음 과 같 습 니 다.
public enum LifecycleState {
NEW, //
INITIALIZING, INITIALIZED, //
STARTING, STARTED, //
SUSPENDING, SUSPENDED, //
RESUMING, RESUMED,//
DESTROYING, DESTROYED,//
FAILED;//
}
인터페이스
생명주기 중의 각종 행위 규범 도 하나의 인터페이스 로 정의 해 야 한다.다음 과 같다.
public interface ILifecycle {
/**
*
*
* @throws LifecycleException
*/
public void init() throws LifecycleException;
/**
*
*
* @throws LifecycleException
*/
public void start() throws LifecycleException;
/**
*
*
* @throws LifecycleException
*/
public void suspend() throws LifecycleException;
/**
*
*
* @throws LifecycleException
*/
public void resume() throws LifecycleException;
/**
*
*
* @throws LifecycleException
*/
public void destroy() throws LifecycleException;
/**
*
*
* @param listener
*/
public void addLifecycleListener(ILifecycleListener listener);
/**
*
*
* @param listener
*/
public void removeLifecycleListener(ILifecycleListener listener);
}
라 이 프 사이클 상태 전환 이 발생 할 때 특정한 사건 에 관심 이 있 는 감청 자 를 촉발 시 켜 야 할 수 있 으 므 로
ILifeCycle
도 감청 자 를 추가 하고 제거 할 수 있 는 두 가지 방법 을 정의 했다.각각:public void addLifecycleListener(ILifecycleListener listener);
과 public void removeLifecycleListener(ILifecycleListener listener);
감청 자 도 하나의 인터페이스 로 그 행위 규범 을 정의 한다.다음 과 같다.public interface ILifecycleListener {
/**
*
*
* @param event
*/
public void lifecycleEvent(LifecycleEvent event);
}
라 이 프 사이클 사건 은
LifecycleEvent
에서 다음 과 같이 표시 합 니 다.public final class LifecycleEvent {
private LifecycleState state;
public LifecycleEvent(LifecycleState state) {
this.state = state;
}
/**
* @return the state
*/
public LifecycleState getState() {
return state;
}
}
골격 실현
ILifecycle 인터페이스 가 있 으 면 이 인 터 페 이 스 를 실현 하 는 모든 종 류 는 생명주기 관리 대상 이 될 것 이다.이 종 류 는 socket 감청 서비스 일 수도 있 고 특정한 모듈 을 대표 할 수도 있다.그럼 저 희 는 ILifecycle 만 실현 하면 되 는 거 아니에요?이렇게 말 할 수 있 지만 각 생명주기 관리 대상 이 생명주기 의 각 단계 에서 공 통 된 행 위 를 하 는 것 을 감안 하면 다음 과 같다.
AbstractLifeCycle
를 제공 하고ILifeCycle
의 골조 로 서 실현 하 는 것 은 중요 한 의 미 를 가진다.이렇게 하면 많은 중복 코드 를 피하 고 구 조 를 더욱 선명 하 게 한다.이 추상 류 는ILifeCycle
에서 정 의 된 모든 인터페이스 방법 을 실현 하고 해당 하 는 추상 적 인 방법 을 추가 하여 하위 클래스 를 실현 하도록 합 니 다.AbstractLifeCycle
이렇게 실현 할 수 있 습 니 다.public abstract class AbstractLifecycle implements ILifecycle {
private List listeners = new CopyOnWriteArrayList();
/**
* state
*/
private LifecycleState state = LifecycleState.NEW;
/*
* @see ILifecycle#init()
*/
@Override
public final synchronized void init() throws LifecycleException {
if (state != LifecycleState.NEW) {
return;
}
setStateAndFireEvent(LifecycleState.INITIALIZING);
try {
init0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString(
"Failed to initialize {0}, Error Msg: {1}", toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.INITIALIZED);
}
protected abstract void init0() throws LifecycleException;
/*
* @see ILifecycle#start()
*/
@Override
public final synchronized void start() throws LifecycleException {
if (state == LifecycleState.NEW) {
init();
}
if (state != LifecycleState.INITIALIZED) {
return;
}
setStateAndFireEvent(LifecycleState.STARTING);
try {
start0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString("Failed to start {0}, Error Msg: {1}",
toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.STARTED);
}
protected abstract void start0() throws LifecycleException;
/*
* @see ILifecycle#suspend()
*/
@Override
public final synchronized void suspend() throws LifecycleException {
if (state == LifecycleState.SUSPENDING || state == LifecycleState.SUSPENDED) {
return;
}
if (state != LifecycleState.STARTED) {
return;
}
setStateAndFireEvent(LifecycleState.SUSPENDING);
try {
suspend0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString("Failed to suspend {0}, Error Msg: {1}",
toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.SUSPENDED);
}
protected abstract void suspend0() throws LifecycleException;
/*
* @see ILifecycle#resume()
*/
@Override
public final synchronized void resume() throws LifecycleException {
if (state != LifecycleState.SUSPENDED) {
return;
}
setStateAndFireEvent(LifecycleState.RESUMING);
try {
resume0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString("Failed to resume {0}, Error Msg: {1}",
toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.RESUMED);
}
protected abstract void resume0() throws LifecycleException;
/*
* @see ILifecycle#destroy()
*/
@Override
public final synchronized void destroy() throws LifecycleException {
if (state == LifecycleState.DESTROYING || state == LifecycleState.DESTROYED) {
return;
}
setStateAndFireEvent(LifecycleState.DESTROYING);
try {
destroy0();
} catch (Throwable t) {
setStateAndFireEvent(LifecycleState.FAILED);
if (t instanceof LifecycleException) {
throw (LifecycleException) t;
} else {
throw new LifecycleException(formatString("Failed to destroy {0}, Error Msg: {1}",
toString(), t.getMessage()), t);
}
}
setStateAndFireEvent(LifecycleState.DESTROYED);
}
protected abstract void destroy0() throws LifecycleException;
/*
* @see
* ILifecycle#addLifecycleListener(ILifecycleListener)
*/
@Override
public void addLifecycleListener(ILifecycleListener listener) {
listeners.add(listener);
}
/*
* @see
* ILifecycle#removeLifecycleListener(ILifecycleListener)
*/
@Override
public void removeLifecycleListener(ILifecycleListener listener) {
listeners.remove(listener);
}
private void fireLifecycleEvent(LifecycleEvent event) {
for (Iterator it = listeners.iterator(); it.hasNext();) {
ILifecycleListener listener = it.next();
listener.lifecycleEvent(event);
}
}
protected synchronized LifecycleState getState() {
return state;
}
private synchronized void setStateAndFireEvent(LifecycleState newState) throws LifecycleException {
state = newState;
fireLifecycleEvent(new LifecycleEvent(state));
}
private String formatString(String pattern, Object... arguments) {
return MessageFormat.format(pattern, arguments);
}
/*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getClass().getSimpleName();
}
}
이 를 통 해 알 수 있 듯 이 추상 적 인 골조 실현 에서 몇 가지 생명 주기 관리 에서 통용 되 는 일 을 했 고 상태 간 의 전환 이 합 법 적 인지 검사 했다(예 를 들 어 start 전에 init 가 필요 하 다).내부 상 태 를 설정 하고 해당 하 는 감청 자 를 촉발 해 야 한다.
추상 류 는
ILifeCycle
정의 하 는 방법 을 실현 한 후에 해당 하 는 추상 적 인 방법 을 남 겨 서 하위 류 를 실현 하도록 했다.위의 코드 에서 보 듯 이 그 가 남 긴 추상 적 인 방법 은 다음 과 같다.protected abstract void init0() throws LifecycleException;
protected abstract void start0() throws LifecycleException;
protected abstract void suspend0() throws LifecycleException;
protected abstract void resume0() throws LifecycleException;
protected abstract void destroy0() throws LifecycleException;
우아 한 실현
지금까지 우 리 는 인터페이스
ILifeCycle
와 그 골격 실현AbstractLifeCycle
을 정 의 했 고 감청 자 체 제 를 추가 했다.계승AbstractLifecycle
을 작성 하고 그 정의 의 추상 적 인 방법 을 다시 쓸 수 있 을 것 같 습 니 다.so far so good.하지만 시작 하기 전에 우 리 는 또 다른 몇 가지 문 제 를 고려 해 야 한다.
init0
,start0
,suspend0
,resume0
,destroy0
,AbstractLifeCycle
?직접 계승
DefaultLifeCycle
은 모든 추상 적 인 방법 을 실현 해 야 한 다 는 것 을 의미한다.따라서 우 리 는 기본 적 인 실현 이 필요 합 니 다.AbstractLifeCycle
를 계승 하고 모든 추상 적 인 방법 을 실현 해 야 합 니 다.그러나 실제 적 인 일 은 하지 않 습 니 다.do nothing.다만 우리 로 하여 금 이 기본 적 인 실현 류 를 계승 하고 관심 있 는 방법 을 다시 쓰 게 할 뿐이다.그래서 우리 의
DefaultLifeCycle
이렇게 탄생 했다.public class DefaultLifecycle extends AbstractLifecycle {
/*
* @see AbstractLifecycle#init0()
*/
@Override
protected void init0() throws LifecycleException {
// do nothing
}
/*
* @see AbstractLifecycle#start0()
*/
@Override
protected void start0() throws LifecycleException {
// do nothing
}
/*
* @see AbstractLifecycle#suspend0()
*/
@Override
protected void suspend0() throws LifecycleException {
// do nothing
}
/*
* @see AbstractLifecycle#resume0()
*/
@Override
protected void resume0() throws LifecycleException {
// do nothing
}
/*
* @see AbstractLifecycle#destroy0()
*/
@Override
protected void destroy0() throws LifecycleException {
// do nothing
}
}
DefaultLifeCycle
에 대해 말하자면,do nothing 는 그 직책 이다.따라서 다음 에 우 리 는 자신의 실현 류,계승DefaultLifeCycle
를 쓰 고 관심 있 는 생명 주기 방법 을 다시 쓸 수 있다.예 를 들 어 저 는 초기 화,시작,소각 할 때 만 작업 을 할 수 있 는 유형 이 있 습 니 다.그러면 이렇게 쓸 수 있 습 니 다.
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketServer extends DefaultLifecycle {
private ServerSocket acceptor = null;
private int port = 9527;
/*
* @see DefaultLifecycle#init0()
*/
@Override
protected void init0() throws LifecycleException {
try {
acceptor = new ServerSocket(port);
} catch (IOException e) {
throw new LifecycleException(e);
}
}
/*
* @see DefaultLifecycle#start0()
*/
@Override
protected void start0() throws LifecycleException {
Socket socket = null;
try {
socket = acceptor.accept();
//do something with socket
} catch (IOException e) {
throw new LifecycleException(e);
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*
* @see DefaultLifecycle#destroy0()
*/
@Override
protected void destroy0() throws LifecycleException {
if (acceptor != null) {
try {
acceptor.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
이곳 의 ServerSocket 에서 init 0 은 socket 감청 을 초기 화하 고 start 0 은 socket 연결 을 가 져 오기 시 작 했 으 며 destroy 0 은 socket 감청 을 없 앴 습 니 다.이 생명 주기 관리 체제 에서 우 리 는 자원 을 쉽게 관리 하고 자원 이 닫 히 지 않 은 상황 이 발생 하지 않 으 며 구조 와 모듈 화가 더욱 뚜렷 해 질 것 이다.
막바지
여기까지 본 고 는 간단 하고 간단 한 생명 주기 관리 체 제 를 실현 하고 모든 실현 코드 를 제시 했다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.