Parlons d'abord de ça
Récemment, j'ai étudié une base de données MySQL open source nationale. Après avoir abaissé sa dernière version du code pour éclipser, le démarrer et effectuer divers tests et suivi du code. Quand je veux le fermer après l'avoir utilisé, je retire sa classe d'arrêt et je veux l'exécuter. J'ai trouvé que seules les lignes de code suivantes ont été écrites dans cette classe, donc j'ai senti que j'étais beaucoup blessé en un instant.
public static void main (String [] args) {System.out.println (new Date () + ", serveur d'arrêt!"); }Lorsque ce middleware est démarré et s'exécute, l'écoute est activée, de nombreux threads commencent à fonctionner et il existe de nombreuses connexions de socket. Mais il n'y a pas de moyen élégant de l'éteindre. Donc, en désespoir de cause, je ne pouvais qu'aller au petit point rouge de l'éclipse et arrêter avec force la machine virtuelle.
S'il s'agit d'un logiciel avec une bonne architecture, un logiciel clair et modulaire, en particulier un logiciel de type serveur, il est très important d'avoir un ensemble de mécanismes de gestion du cycle de vie. Non seulement il peut gérer le cycle de vie de chaque module, mais il peut également être plus élégant lors du démarrage et de l'arrêt de l'ensemble du logiciel sans manquer de ressources.
Mise en œuvre simple du mécanisme du cycle de vie
État du cycle de vie
L'état du cycle de vie d'un module a généralement ce qui suit:
Nouveau-né-> Initialisation-> Initialisation terminée-> Initialisation-> Initialisation terminée-> Initialisation-> pause-> pause-> Recomering-> Recomering-> destrie-> destruction-> destruction. Si la conversion entre les états échoue, elle entrera dans un autre état: l'échec.
Pour ce faire, vous pouvez utiliser une classe d'énumération pour énumérer ces états, comme indiqué ci-dessous:
Public Enum LifecycleState {new, // NewSen Initializing, Initialized, // initialize démarrage, a commencé, // commencer à suspendre, a suspendu, // pause reprendre, reprendre, // restauration destruction, détruit, // détruit a échoué; // a échoué}interface
Diverses normes de comportement dans le cycle de vie nécessitent également une interface pour définir, comme indiqué ci-dessous:
Interface publique ilifecycle {/ ** * Initialize * * @throws lifeccycleException * / public void init () lève LifecCycleException; / ** * start * * @throws lifecycleException * / public void start () lève LifecCycleException; / ** * Pause * * @throws lifecycleException * / public void suspendre () lève LifecCycleException; / ** * Recover * * @throws lifecycleException * / public void ressume () lève LifecCycleException; / ** * Détroyer * * @throws lifecycleException * / public void destre () lève LifeccycleException; / ** * Ajouter un écouteur de cycle de vie * * @param écouteur * / public void addlifecycleListener (ilifecycleListener auditeur); / ** * Supprimer l'auditeur de cycle de vie * * @param écouteur * / public void removelifecycleListener (ilifecyclelistener écouteur);}Lorsqu'une transition d'état de cycle de vie se produit, les auditeurs qui sont intéressés par un certain type d'événement peuvent devoir être déclenchés, donc Ilifecycle définit également deux méthodes pour ajouter et supprimer les auditeurs. Ce sont: public void addlifecycleListener (écouteur ilifecycleListener); et public Void RemoveliFecycleListener (écouteur ilifecycleListener);
L'auditeur définit également ses normes de comportement par une interface, comme indiqué ci-dessous:
Interface publique IlifecycleListener {/ ** * Gérer les événements de cycle de vie * * @param événements Events Lifecycle * / public void lifeCycleEvent (LifeCycleEvent Event);}Les événements de cycle de vie sont représentés par LifeCycleEvent, comme indiqué ci-dessous:
Public Final Class LifECycleEvent {Private Lifecyclestate State; Public LifecycleEvent (LifecycleState State) {this.state = state; } / ** * @return l'état * / public lifecyclestate getState () {return state; }}Mise en œuvre du squelette
Avec l'interface Ilifecycle, toute classe qui implémente cette interface sera utilisée comme objet de gestion du cycle de vie. Cette classe peut être un service d'écoute de douille, ou il peut représenter un module spécifique, etc. Avons-nous simplement besoin d'implémenter Ilifecycle? On peut le dire, mais étant donné que chaque objet de gestion du cycle de vie aura des comportements communs à divers stades du cycle de vie, tels que:
Définir votre propre état de cycle de vie pour vérifier si la transition de l'État est conforme à la logique pour informer l'auditeur que l'état du cycle de vie a changé. Par conséquent, il est d'une grande importance de fournir une classe abstraite abstraitelifecycle comme mise en œuvre du squelette d'Ilifecycle, qui évite beaucoup de code en double et rend l'architecture plus claire. Cette classe abstraite implémentera toutes les méthodes d'interface définies dans Ilifecycle et ajoutera des méthodes abstraites correspondantes pour l'implémentation des sous-classes. Abstractlifecycle peut être mis en œuvre comme ceci:
classe abstraite de la classe AbstractLifecycle implémente ilifecycle {Liste privée <IlifecycleListener> écouteurs = new CopyOnwriteArrayList <IlifecycleListener> (); / ** * L'état représente l'état de cycle de vie actuel * / Private LifecycleState State = lifecycleState.new; / * * @see ilifecycle # init () * / @Override public final synchronisé void init () lève lifecycleException {if (state! = lifecyclestate.new) {return; } setStateAndFireevent (lifecyclestate.Initializing); essayez {init0 (); } catch (Throwable T) {setStateAndfiReEvent (lifecyclestate.failed); if (t instanceof lifeccycleException) {throw (lifecycleException) t; } else {Throw New LifECycleException (FormatString ("n'a pas réussi à initialiser {0}, error msg: {1}", toString (), t.GetMessage ()), t); }} setStateAndfiReEvent (lifecyclestate.Initialized); } Résumé protégé void init0 () lève LifeCycleException; / * * @see ilifecycle # start () * / @Override public final synchronisé void start () lève LifeccycleException {if (state == lifecyclestate.new) {init (); } if (état! = lifecycleState.Initialized) {return; } setStateAndFireevent (lifecyclestate.starting); essayez {start0 (); } catch (Throwable T) {setStateAndfiReEvent (lifecyclestate.failed); if (t instanceof lifeccycleException) {throw (lifecycleException) t; } else {Throw New LifECycleException (FormatString ("n'a pas réussi à démarrer {0}, error msg: {1}", toString (), t.getMessage ()), t); }} setStateAndfiReEvent (lifecyclestate.started); } Résumé protégé void start0 () lève LifeCycleException; / * * @see ilifecycle # suspension () * / @Override public final synchronisé void suspendre () lève LifeccycleException {if (state == lifecyclestate.susPending || state == lifcycleState.suspendation) {return; } if (state! = lifecycleState.started) {return; } setStateAndFireEvent (LifecycleState.susprend); essayez {suspend0 (); } catch (Throwable T) {setStateAndfiReEvent (lifecyclestate.failed); if (t instanceof lifeccycleException) {throw (lifecycleException) t; } else {Throw New LifECycleException (FormatString ("n'a pas réussi à suspendre {0}, error msg: {1}", toString (), t.GetMessage ()), t); }} setStateAndfiReEvent (lifecycleState.suspeded); } Résumé protégé void suspend0 () lève LifeccycleException; / * * @see ilifecycle # ressume () * / @Override public final synchronisé void resu () lève lifecycleException {if (state! = lifecycleState.suspedend) {return; } setStateAndFireevent (lifecyclestate.resuming); essayez {repume0 (); } catch (Throwable T) {setStateAndfiReEvent (lifecyclestate.failed); if (t instanceof lifeccycleException) {throw (lifecycleException) t; } else {Throw New LifECycleException (FormatString ("n'a pas réussi à reprendre {0}, error msg: {1}", toString (), t.GetMessage ()), t); }} setStateAndfiReEvent (lifecyclestate.resumed); } Résumé protégé void remer0 () lève LifecCycleException; / * * @see ilifecycle # destrust () * / @Override public final synchronisé void destrust () lève LifeccycleException {if (state == lifecyclestate.destroying || state == lifecyclestate.destroyed) {return; } setStateAndFireEvent (LifecycleState.Desttoyy); essayez {destrust0 (); } catch (Throwable T) {setStateAndfiReEvent (lifecyclestate.failed); if (t instanceof lifeccycleException) {throw (lifecycleException) t; } else {Throw New LifECycleException (FormatString ("n'a pas détruit {0}, error msg: {1}", toString (), t.getMessage ()), t); }} setStateAndfiReEvent (lifecyclestate.destroyed); } Résumé protégé void destrust0 () lève LifeCycleException; / * * @see * ilifecycle # addlifecycleListener (ilifecycleListener) * / @Override public void addlifecycleListener (ilifecycleListener écouteur) {auditers.add (écouteur); } / * * @see * ilifecycle # removeListener (ilifecycleListener) * / @Override public void removeLifecycleListener (ilifecycleListener Écouteur) {Liditers.Remove (écouteur); } private void firelifecycleEvent (LifeCycleEvent Event) {for (iterator <ilifecycleListener> it = audivers.iterator (); it.hasnext ();) {ilifecycleListener écouteur = it.next (); auditeur.lifecycleEvent (événement); }} Synchronisé de lifycyclestate protégée protégée GetState () {return State; } private synchronisé void SetStateAndFireEvent (LifecycleState NewState) lève LifecCycleException {State = NewState; FirelifecycleEvent (nouveau LifecycleEvent (état)); } private String FormatString (modèle de chaîne, objet ... arguments) {return MessageFormat.Format (modèle, arguments); } / * * @see java.lang.object # toString () * / @Override public String toString () {return getClass (). getIMPLename (); }}On peut voir que la mise en œuvre du squelette de classe abstraite fait plusieurs choses courantes dans la gestion du cycle de vie, vérifiant si la transition entre les États est légale (par exemple, elle doit être init avant de démarrer), la définition de l'état interne et le déclenchement de l'auditeur correspondant.
Une fois que la classe abstraite a mis en œuvre la méthode définie par ilifecycle, il laisse des méthodes abstraites correspondantes pour que sa sous-classe puisse mettre en œuvre. Comme indiqué dans le code ci-dessus, les méthodes abstraites laissées incluent les éléments suivants:
Résumé protégé void init0 () lève LifeCycleException; Résumé protégé vide start0 () lève LifeCycleException; Résumé protégé void suspendu0 () lève LifeCycleException; Résumé protégé void remer0 () lève LifeCycleException; Résumé protégé void destroy0 () lève LifeCycleException;
Mise en œuvre élégante
Jusqu'à présent, nous avons défini l'interface ilifecycle, et son squelette implémente Abstractlifecycle et ajouté un mécanisme d'écoute. Il semble que nous puissions commencer à écrire une classe pour hériter de l'abstractlifecycle et réécrire la méthode abstraite qu'il définit, jusqu'à présent.
Mais avant de commencer, nous devons considérer plusieurs autres problèmes.
Nos classes d'implémentation sont-elles intéressées par toutes les méthodes abstraites?
Chaque implémentation doit-elle mettre en œuvre init0, start0, suspend0, remise0, destroy0, destre0?
Nos cours de vie ou nos modules ne soutiennent pas la suspension ou la récupération?
Héritage directement de l'abstractlifecycle signifie que toutes ses méthodes abstraites doivent être mises en œuvre.
Nous avons donc également besoin d'une implémentation par défaut, de défaut de valeur par défaut, de hériter de l'abstractlifecycle et d'implémenter toutes les méthodes abstraites, mais il ne fait rien de pratique, ne fait rien. Laissez-nous simplement la classe d'implémentation réelle hériter de cette classe d'implémentation par défaut et remplacer la méthode d'intérêt.
Ainsi, notre LifeCycle de Default est né:
classe publique Defaultlifecycle étend AbstractLifecycle {/ * * @see abstractlifecycle # init0 () * / @Override Protected void init0 () lève LifecCycleException {// ne rien faire} / * * @see abstractlifecycle # start0 () * / @Override Protected start0 () throws lifeccycleexception {// Do} Abstractlifecycle # suspension0 () * / @Override Protected void Suspendinternal () lève LifecyCycleException {// ne rien faire} / * * @see abstractlifecycle # ressume0 () * / @Override Protected void ressume0 () lance LifeccycleException {// / * * * * @see abstractlifecy void destroy0 () lève LifeCycleException {// ne rien faire}} Pour Defaultlifecycle, ne faites rien est sa responsabilité.
Ainsi, nous pouvons ensuite écrire notre propre classe d'implémentation, hériter de défaut de vie et réécrire ces méthodes d'intérêt du cycle de vie.
Par exemple, j'ai une classe qui n'a besoin que de tâches lors de l'initialisation, du démarrage et de la destruction, afin que je puisse l'écrire comme ceci:
import java.io.ioException; import java.net.serversocket; import java.net.socket; public class socketserver étend defaultlifecycle {private serveSocket acceptor = null; port int privé = 9527; / * * @see defaultlifecycle # init0 () * / @Override Protected void init0 () lève LifecCycleException {try {acceptor = new Serversocket (port); } catch (ioException e) {lancez une nouvelle vie de LifecycleException (e); }} / * * @see defaultlifecycle # start0 () * / @Override Protected void start0 () lève LifecCycleException {socket socket = null; essayez {socket = acceptor.accept (); // Faites quelque chose avec socket} catch (ioException e) {lancez un nouveau lifecycleException (e); } enfin {if (socket! = null) {try {socket.close (); } catch (ioException e) {// TODO Bloc de capture généré automatiquement e.printStackTrace (); }}}}} / * * @see defaultlifecycle # destrust0 () * / @Override Protected void destred0 () lève LifecCycleException {if (Acceptor! = null) {try {acceptor.close (); } catch (ioException e) {// TODO Bloc de capture généré automatiquement e.printStackTrace (); }}}} Dans SERVERSOCKET ICI, INIT0 Initialize Socket Écoute, Start0 commence à obtenir la connexion de socket, Destroy0 détruit l'écoute du socket.
Dans ce mécanisme de gestion du cycle de vie, nous gérerons facilement les ressources, et il n'y aura pas d'arrêt des ressources, et l'architecture et la modularité seront plus claires.
fin
Jusqu'à présent, cet article a mis en œuvre un mécanisme de gestion du cycle de vie simple et donné tous les codes de mise en œuvre. Après cela, tout le code source sera placé sur GitHub. Veuillez faire attention à la mise à jour de cet article.