먼저 그것에 대해 이야기합시다
최근에 나는 국내 오픈 소스 MySQL 데이터베이스 미들웨어를 연구하고 있습니다. 최신 버전의 코드를 Eclipse로 끌어 올린 후 다양한 테스트 및 코드 추적을 수행합니다. 사용 후 닫고 싶을 때 스톱 클래스를 꺼내고 실행하고 싶습니다. 나는이 수업에서 다음 줄의 코드 만 쓰여졌다는 것을 알았으므로 순식간에 많은 상처를 받았다고 느꼈습니다.
public static void main (String [] args) {System.out.println (new date () + ", 서버 종료!"); }이 미들웨어가 시작되고 실행되면 청취가 활성화되고 많은 스레드가 실행되기 시작하며 소켓 연결이 많이 있습니다. 그러나 그것을 끄는 우아한 방법은 없습니다. 절망적으로, 나는 일식의 작은 빨간 점으로 가서 VM을 강력하게 막을 수있었습니다.
우수한 아키텍처, 모듈성 및 명확한 구조, 특히 서버와 같은 소프트웨어를 갖춘 소프트웨어 인 경우 수명주기 관리 메커니즘 세트를 갖는 것이 매우 중요합니다. 각 모듈의 수명주기를 관리 할 수있을뿐만 아니라 리소스를 놓치지 않고 전체 소프트웨어를 시작하고 중지 할 때 더 우아 할 수도 있습니다.
수명주기 메커니즘의 간단한 구현
수명주기 상태
모듈의 수명주기 상태는 일반적으로 다음과 같습니다.
신생아-> 초기화-> 초기화 완료-> 초기화-> 초기화 완료-> 초기화-> 초기화-> 일시화-> 복구-> 복구-> 파괴-> 파괴-> 파괴. 상태 간의 전환이 실패하면 다른 상태에 들어갑니다 : 실패.
이렇게하려면 아래와 같이 열거 클래스를 사용하여 이러한 상태를 열거 할 수 있습니다.
public enum lifecyclestate {new, // newsen 초기화, 초기화, 초기화, // 시작, 시작, 시작, 시작, 시작, 일시 중지, // 재개, 재개, // 파괴, 파괴, 파괴 실패; // 실패}인터페이스
수명주기의 다양한 행동 규범은 다음과 같이 정의하기 위해 인터페이스가 필요합니다.
public interface ilifecycle { / ** * 초기화 * * @throws lifecycleException * / public void init ()는 LifeCycleException을 던졌습니다. / ** * start * * @throws LifeCycleException */ public void start ()는 LifeCycleException을 던졌습니다. / ** * pause * * @throws lifecycleException */ public void spelend ()는 LifeCycleException을 던졌습니다. / ** * 복구 * * @Throws LifeCycleException */ public void recume ()가 LifeCycleException을 던졌습니다. / ** * Destrove * * @Throws LifeCycleException */ public void destroy ()가 LifecycleException을 던졌습니다. / ** * 라이프 사이클 리스너 추가 * * @param 리스너 */ public void addlifecyclelistener (ilifecyclelistener 리스너); / ** * 수명주기 리스너 삭제 * * @param 리스너 */ public void removelifecyclelistener (ilifecyclelistener 리스너);}수명주기 상태 전환이 발생하면 특정 유형의 이벤트에 관심이있는 청취자를 트리거해야 할 수도 있으므로 Ilifecycle은 청취자를 추가하고 제거하는 두 가지 방법을 정의합니다. 그것들은 : public void addlifecyclelistener (ilifecyclelistener 리스너); 및 공개 void removelifecyclelistener (ilifecyclelistener 리스너);
청취자는 또한 아래와 같이 인터페이스로 행동 규범을 정의합니다.
공개 인터페이스 ilifecyclelistener { / *** 수명주기 핸들 핸들** @param 이벤트 라이프 사이클 이벤트* / public void lifecyceycleevent (lifecycyevent event);}수명주기 이벤트는 다음과 같이 LifecycleEvent로 표시됩니다.
공개 최종 클래스 LifeCycleEvent {Private LifecyClestate State; public lifecycleevent (lifecyclestate state) {this.state = state; } / ** * @State * / Public LifeCyClestate getState () {return state; }}골격 구현
Ilifecycle 인터페이스를 사용하면이 인터페이스를 구현하는 클래스는 수명주기 관리 객체로 사용됩니다. 이 클래스는 소켓 청취 서비스 일 수 있거나 특정 모듈 등을 나타낼 수 있습니다. 그렇다면 ilifecycle을 구현하면됩니다. 말할 수 있지만, 각 수명주기 관리 객체가 수명주기의 다양한 단계에서 다음과 같은 공통의 동작을 가질 것이라고 말할 수 있습니다.
자신의 수명주기 상태를 설정하여 상태의 전환이 리스너에게 수명주기 상태가 변경되었음을 알리기 위해 논리에 부합하는지 확인합니다. 따라서 Ilifecycle의 골격 구현으로 추상 클래스 AbstractLifecycle을 제공하는 것은 큰 의미가 있으며, 이는 많은 중복 코드를 피하고 아키텍처를 더 명확하게 만듭니다. 이 추상 클래스는 ilifecycle에 정의 된 모든 인터페이스 방법을 구현하고 서브 클래스 구현을위한 해당 추상 방법을 추가합니다. AbstractLifeCycle은 다음과 같이 구현할 수 있습니다.
공개 초록 클래스 AbstractLifeCycle은 Ilifecycle {개인 목록 <ilifecyclElistener> 리스너 = 새로운 copyonwritearraylist <ilifecyclelistener> (); / *** 상태는 현재 수명주기 상태를 나타냅니다. / * * @see ilifecycle#init () */ @override public final synchronized void init ()는 lifecycleException {if (state! = lifecyclest.new) {return; } setStateAndFireeEvent (LifeCyClestate.initializing); {init0 (); } catch (Throwable t) {setStateAndFireevent (LifeCyClestate.Failed); if (t LifecycleException의 인스턴스) {Throw (LifeCycleException) t; } else {throw new lifecycleException (포맷 스트링 ( "{0} 초기화 실패, 오류 msg : {1}", toString (), t.getMessage ()), t); }} setStateAndFireeEvent (lifeCyClestate.initialized); } 보호 된 초록 void init0 ()는 LifeCycleException을 던졌습니다. / * * @see ilifecycle#start () */ @override public final synchronized void start ()가 lifecycleException {if (state == lifecyclestate.new) {init (); } if (state! = lifecyclestate.initialized) {return; } setStateAndFireeEvent (lifecyclestate.starting); try {start0 (); } catch (Throwable t) {setStateAndFireevent (LifeCyClestate.Failed); if (t LifecycleException의 인스턴스) {Throw (LifeCycleException) t; } else {throw new lifecycleException (포맷 스트링 }} setStateAndfireevent (lifecyclestate.started); } 보호 된 초록 void start0 ()는 LifeCycleException을 던졌습니다. / * * @see ilifecycle#sultend () */ @override public final synchronized void void spelend () lifecycleException {if (state == lifecyclestate.suspending || state == lifecyclestate.suspended) {return; } if (state! = lifecyclestate.started) {return; } setStateAndFireeEvent (LifeCyClestate.suspending); try {sustend0 (); } catch (Throwable t) {setStateAndFireevent (LifeCyClestate.Failed); if (t LifecycleException의 인스턴스) {Throw (LifeCycleException) t; } else {throw new lifecycleException (포맷 스트링 }} setStateAndFireeEvent (lifecyclestate.suspended); } 보호 된 초록 void sportend0 ()는 LifeCycleException을 던졌습니다. / * * @see ilifecycle#recume () */ @override public final synchronized void resume () lifecycleException {if (state! = lifecyclestate.suspended) {return; } setStateAndFireeEvent (LifeCyClestate.Resuming); try {recume0 (); } catch (Throwable t) {setStateAndFireevent (LifeCyClestate.Failed); if (t LifecycleException의 인스턴스) {Throw (LifeCycleException) t; } else {throw new lifecycleException (formatstring ( "실패 {0}, error msg : {1}", toString (), t.getMessage ()), t); }} setStateAndFireevent (LifeCyClestate.resumed); } 보호 된 초록 void resume0 ()는 LifeCycleException을 던졌습니다. / * * @see ilifecycle#destroy () */ @override public final synchronized void void void destress () lifecycleException {if (state == lifecyclestate.destroying || state == lifecyclest.destroyed) {return; } setStateAndFireeEvent (LifeCyClestate.destroying); try {destroy0 (); } catch (Throwable t) {setStateAndFireevent (LifeCyClestate.Failed); if (t LifecycleException의 인스턴스) {Throw (LifeCycleException) t; } else {throw new lifecycleException (포맷 스트링 }} setStateAndfireevent (lifecyclestate.destroyed); } 보호 된 초록 void destrove0 ()는 LifeCycleException을 던졌습니다. / * * @see * ilifecycle#addlifecyclelistener (ilifecyclelistener) */ @override public void addlifecyclelistener (ilifecyclelistener 리스너) {haresers.add (리스너); } / * * @see * ilifecycle#removelistener (ilifecyclelistener) * / @override public void removelifecyclelistener (ilifecyclelistener listener) {haresers.remove (Lister); } private void firelifecycleEvent (lifecycleevent event) {for (iterator <ilifecyclelistener> it = listeners.iterator (); it.hasnext ();) {ilifecyclelistener threater = it.next (); Listener.lifecycleEvent (이벤트); }} 보호 된 동기화 된 LifeCyClestate getState () {return state; } private synchronized void setStateAndFireevent (LifeCyclestate Newstate)는 LifeCycleException {state = newstate; firelifecycleevent (New Lifecyceycleevent (state)); } private String formatstring (문자열 패턴, 객체 ... 인수) {return messageformat.format (패턴, 인수); } / * * @see java.lang.object#tostring () * / @override public String toString () {return getClass (). getSimplename (); }}추상 클래스 골격 구현은 수명주기 관리에서 몇 가지 공통된 작업을 수행하여 상태 간의 전환이 합법적인지 (예 : 시작하기 전에 시작해야 함) 내부 상태를 설정하고 해당 리스너를 트리거합니다.
추상 클래스는 Ilifecycle에 의해 정의 된 방법을 구현 한 후에는 서브 클래스가 구현하기위한 해당 추상 방법을 남깁니다. 위의 코드에서 볼 수 있듯이 추상 방법에는 다음이 포함됩니다.
보호 된 추상적 void init0 ()는 수명 인사를 던졌습니다. 보호 된 초록 void start0 ()는 LifecycleException을 던졌습니다. 보호 된 초록 void spelend0 ()는 LifecycleException을 던졌습니다. 보호 된 초록 void resume0 ()는 LifecycleException을 던졌습니다. 보호 된 추상적 void destrove0 ()는 수명 체류를 던졌습니다.
우아한 구현
지금까지 우리는 인터페이스 ilifecycle을 정의했으며 해골은 AbstractLifeCycle을 구현하고 리스너 메커니즘을 추가했습니다. 우리는 수업을 쓰기 시작하여 AbstractLifeCycle을 상속하고 지금까지 정의하는 추상적 인 방법을 다시 작성할 수있는 것 같습니다.
그러나 시작하기 전에 다른 몇 가지 문제를 고려해야합니다.
구현 클래스는 모든 추상 방법에 관심이 있습니까?
각 구현은 init0, start0, sultend0, recume0, destroy0, destrove0을 구현해야합니까?
때로는 우리의 생활 수업이나 모듈이 서스펜션이나 회복을 지원하지 않습니까?
AbstractLifeCycle을 직접 상속한다는 것은 모든 추상 방법을 구현해야 함을 의미합니다.
또한 기본 구현, DefaultLifeCycle, AbstractLifeCycle을 상속하고 모든 추상 방법을 구현해야하지만 실용적인 작업은 아니며 아무것도하지 않습니다. 실제 구현 클래스 가이 기본 구현 클래스를 상속하고 관심있는 방법을 무시하십시오.
따라서 우리의 DefaultLifeCycle이 탄생했습니다.
public class defaultlifecycle 확장 actordLifeCycle { / * * @see actractLifeCycle#init0 () * /@override protected void init0 ()는 LifeCycleException {// do nothing} / * * * @see AbstractLifeCycle#start0 () * /@override propoid void start0 () nothing {// do {do {do {do in nothing} / * @AbstractLifeCycle#sentrend0 () */ @override protected void speldInternal ()가 lifecycleException {// do nothing}/ * * * * @see actractLifeCycle#reSume0 () */ @OverRide protected void restume 0 () lifecyclexception {/ * * * * @seee# * @see########## @override protected void destroy0 ()가 LifeCycleException을 던지려면 {// do nothing}} DefaultLifeCycle의 경우 아무것도하지 않습니다.
다음으로 자체 구현 클래스를 작성하고 DefaultLifeCycle을 상속하고 해당 수명주기 관심 메소드를 다시 작성할 수 있습니다.
예를 들어, 초기화, 시작 및 파괴 중에 만 작업을 수행하면 필요한 수업이 있으므로 다음과 같이 쓸 수 있습니다.
import java.io.ioexception; import java.net.serversocket; import java.net.socket; public class socketserver 확장 defaultLifeCycle {private serversocket acceptor = null; 개인 int 포트 = 9527; / * * @defaultLifeCycle#init0 () */ @override protected void init0 ()는 LifeCycleException {try {acceptor = new serversocket (port); } catch (ioException e) {새로운 수명력이 나오는 경우 (E); }} / * * @defaultLifeCycle#start0 () * / @override protected void start0 ()가 LifeCycleException {Socket Socket = null; {socket = acceptor.acrect (); // 소켓으로 무언가를 수행} catch (ioException e) {새 LifeCycleException (e)을 던지십시오. } 마지막으로 {if (socket! = null) {try {socket.close (); } catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); }}}}} / * * @defaultLifeCycle#destroult0 () * / @override protected void destroy0 ()가 LifeCycleException {if (acceptor! = null) {try {acceptor.close (); } catch (ioexception e) {// todo 자동 생성 캐치 블록 e.printstacktrace (); }}}} 여기서 Serversocket에서 init0은 소켓 청취를 초기화하고 START0은 소켓 연결을 얻기 위해 시작하고 Destroy0은 소켓 청취를 파괴합니다.
이 수명주기 관리 메커니즘 하에서 우리는 리소스를 쉽게 관리 할 것이며 리소스 종료가 없을 것이며 아키텍처와 모듈성이 더 명확해질 것입니다.
끝
지금 까지이 기사는 간단한 수명주기 관리 메커니즘을 구현하고 모든 구현 코드를 제공했습니다. 그 후 모든 소스 코드는 Github에 배치됩니다. 이 기사의 업데이트에주의하십시오.