자바 생명주기 관리 메커니즘 실현

우선 잡담 을 하고 나 서 다시 이야기 하 자
최근 한 국산 오픈 소스 인 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?
  • 때때로 우리 의 생명 이 있 는 클래스 나 모듈 은 일시 정지(suspend),회복(resume)을 지원 하지 않 습 니까?

  • 직접 계승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 감청 을 없 앴 습 니 다.이 생명 주기 관리 체제 에서 우 리 는 자원 을 쉽게 관리 하고 자원 이 닫 히 지 않 은 상황 이 발생 하지 않 으 며 구조 와 모듈 화가 더욱 뚜렷 해 질 것 이다.
    막바지
    여기까지 본 고 는 간단 하고 간단 한 생명 주기 관리 체 제 를 실현 하고 모든 실현 코드 를 제시 했다.

    좋은 웹페이지 즐겨찾기