Tomcat7 Source Code Analysis (2) Detailed Explanation of Component Life Cycle

    The core interface that plays the role of life cycle in tomcat is Lifecycle. Look at the method signature of this interface:



    this interface defines all states that all components may be in, adding, acquiring and deleting listener operations, component initialization, starting, stopping, logging out operations and obtaining Current state action.

    The state defined in the Lifecycle interface is also encapsulated into an enumeration class, you can take a look at the source code of LifecycleState:
public enum LifecycleState {
    NEW(false, null),
    INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
    INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
    STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
    STARTING(true, Lifecycle.START_EVENT),
    STARTED(true, Lifecycle.AFTER_START_EVENT),
    STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
    STOPPING(false, Lifecycle.STOP_EVENT),
    STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
    DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
    DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
    FAILED(false, null),
    MUST_STOP(true, null),
    MUST_DESTROY(false, null);

    private final boolean available;
    private final String lifecycleEvent;

    private LifecycleState(boolean available, String lifecycleEvent) {
        this.available = available;
        this.lifecycleEvent = lifecycleEvent;
    }
    public boolean isAvailable() {
        return available;
    }

    /**
     *
     */
    public String getLifecycleEvent() {
        return lifecycleEvent;
    }
}

    It can be seen from the above source code that the LifecycleState enumeration class encapsulates the state in the Lifecycle interface. In addition, the availability flag is added.
Let's start with the familiar StandardServer class and discuss how these components are initialized and started. Take a look at the inheritance diagram of StandardServer:



    This leads to a question, what class is LifecycleBase. Open the source code of this class, you can first see that it implements the Lifecycle interface, that is, it is the top-level class that manages the life cycle of components. Generally, high-level classes like this are abstract, and this class is no exception, it is also abstract.
   
    Let's start to discuss the methods of this class. First, inherit the underlying component class of LifecycleBase, such as StandardServer, which does not need to rewrite the three methods of init, start, and stop. Because these three methods define the commonality of component state transitions. For example, the init method, all components must execute this public method when they are initialized. First paste the source code of this method:
@Override
    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }
        setStateInternal(LifecycleState.INITIALIZING, null, false);

        try {
            initInternal ();
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            setStateInternal(LifecycleState.FAILED, null, false);
            throw new LifecycleException(
                    sm.getString("lifecycleBase.initFail",toString()), t);
        }

        setStateInternal(LifecycleState.INITIALIZED, null, false);
    }

    There are two points to focus on:
   
    1) setStateInternal: The function of this method is to reset the state of the component. And it is accompanied by the execution of event listeners when the state changes. Looking at the code of setStateInternal, it is not difficult to find that its core code is as follows:
this.state = state;
        String lifecycleEvent = state.getLifecycleEvent();
        if (lifecycleEvent != null) {
            fireLifecycleEvent(lifecycleEvent, data);
        }

    Change the component state first, and then see if the state needs to be listened to by the listener. Execute the listener if it is listened to by the listener. But the implementation of the listener is easy to say, how does it come from, and what is its monitoring mechanism?
Now catch up with this method to see its implementation process:
protected void fireLifecycleEvent(String type, Object data) {
        lifecycle.fireLifecycleEvent(type, data);
    }

What is this lifecycle? It is an instance of the LifecycleSupport class. In fact, LifecycleBase is a proxy class of LifecycleSupport. All listener-related methods of LifecycleBase are methods in the called LifecycleSupport. You can look at the method signature of LifecycleSupport:



lifecycle refers to the class that implements the lifecycle interface for which the LifecycleSupport class serves. listeners[] is an array of listeners, addLifecycleListener is to add listeners, when the tomcat container starts, use Digester technology (it doesn't matter if you haven't heard of it, as long as you know that it reads the configuration file and then instantiates the object according to the configuration file) to read the server. The <Listener> tag in the xml file, and then call addLifecycleListener to add the configured Listener to listeners[]. removeLifecycleListener is a remove listener. fireLifecycleEvent loops through each listener in the listener array. The fireLifecycleEvent method is executed when the state mentioned above is changed.

Seeing that, some friends may have forgotten the init method above. Please note that this is only the first point of the two points that need to be paid attention to in the init method. Then start the second point:

2) initInternal method. It is an abstract method which means that the method must be overridden by subclasses. First look at its direct subclass LifecycleMBeanBase. When you see the name of this class, you can think that it may be related to javabean management. Indeed, he overrides the initInternal method, the purpose of which is to register the component with the JMX server. The specific registration process will not be discussed too much, and the update will be explained in detail later. StandardServer also overrides the initInternal method. and the first line is:
super.initInternal();

Calling the parent class is the initInternal method in the LifecycleMBeanBase class. At this time, this sentence cannot be omitted. If it is omitted, the object cannot be registered with the JMX server. This is to be distinguished from the first line of the automatically generated constructor in eclipse, super.init(); writable or not. The key code in the subclass is as follows:
// Initialize our defined Services
        for (int i = 0; i < services.length; i++) {
            services[i].init();
        }

It executes the service's init method. Carefully return to the above logic and organize your ideas, you will find how beautiful the life cycle management of tomcat is!

I extracted the implementation process of the tomcat life cycle from the tomcat source code, and built a small demo. Interested friends can download the debug to organize their ideas, which will be more intuitive.
Address: https://github.com/smallbug-vip/repo

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=327088889&siteId=291194637