LifecycleMBeanBase被许多类继承,本文浅析之(由分析知——jmx是tomcat的基础)
LifecycleMBeanBase继承了LifecycleBase,实现了jmxEnabled,内部依赖org.apache.tomcat.util.modeler.Registry
分别用于生命周期的管理(start,init,stop,destroy),以及jmx——java拓展管理
1 生命周期
All Implemented Interfaces:
, ,
Direct Known Subclasses:
, , , , , , , , ,, , , ,
Lifecycle:
主要实现start stop init destroy方法,并留有startInternal,stopInternal等方法给子类实现
/** * Common interface for component life cycle methods. Catalina components * may implement this interface (as well as the appropriate interface(s) for * the functionality they support) in order to provide a consistent mechanism * to start and stop the component. * * The valid state transitions for components that support {@link Lifecycle} * are: ** start() * ----------------------------- * | | * | init() | * NEW -»-- INITIALIZING | * | | | | ------------------«----------------------- * | | |auto | | | * | | \|/ start() \|/ \|/ auto auto stop() | * | | INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»--- | * | | | | | * | |destroy()| | | * | --»-----«-- ------------------------«-------------------------------- ^ * | | | | * | | \|/ auto auto start() | * | | STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»----- * | \|/ ^ | ^ * | | stop() | | | * | | -------------------------- | | * | | | | | * | | | destroy() destroy() | | * | | FAILED ----»------ DESTROYING ---«----------------- | * | | ^ | | * | | destroy() | |auto | * | --------»----------------- \|/ | * | DESTROYED | * | | * | stop() | * ----»-----------------------------»------------------------------ * * Any state can transition to FAILED. * * Calling start() while a component is in states STARTING_PREP, STARTING or * STARTED has no effect. * * Calling start() while a component is in state NEW will cause init() to be * called immediately after the start() method is entered. * * Calling stop() while a component is in states STOPPING_PREP, STOPPING or * STOPPED has no effect. * * Calling stop() while a component is in state NEW transitions the component * to STOPPED. This is typically encountered when a component fails to start and * does not start all its sub-components. When the component is stopped, it will * try to stop all sub-components - even those it didn't start. * * Attempting any other transition will throw {@link LifecycleException}. * ** The {@link LifecycleEvent}s fired during state changes are defined in the * methods that trigger the changed. No {@link LifecycleEvent}s are fired if the * attempted transition is not valid. * * @author Craig R. McClanahan */public interface Lifecycle { // ----------------------------------------------------- Manifest Constants /** * The LifecycleEvent type for the "component before init" event. */ public static final String BEFORE_INIT_EVENT = "before_init"; /** * The LifecycleEvent type for the "component after init" event. */ public static final String AFTER_INIT_EVENT = "after_init"; /** * The LifecycleEvent type for the "component start" event. */ public static final String START_EVENT = "start"; /** * The LifecycleEvent type for the "component before start" event. */ public static final String BEFORE_START_EVENT = "before_start"; /** * The LifecycleEvent type for the "component after start" event. */ public static final String AFTER_START_EVENT = "after_start"; /** * The LifecycleEvent type for the "component stop" event. */ public static final String STOP_EVENT = "stop"; /** * The LifecycleEvent type for the "component before stop" event. */ public static final String BEFORE_STOP_EVENT = "before_stop"; /** * The LifecycleEvent type for the "component after stop" event. */ public static final String AFTER_STOP_EVENT = "after_stop"; /** * The LifecycleEvent type for the "component after destroy" event. */ public static final String AFTER_DESTROY_EVENT = "after_destroy"; /** * The LifecycleEvent type for the "component before destroy" event. */ public static final String BEFORE_DESTROY_EVENT = "before_destroy"; /** * The LifecycleEvent type for the "periodic" event. */ public static final String PERIODIC_EVENT = "periodic"; /** * The LifecycleEvent type for the "configure_start" event. Used by those * components that use a separate component to perform configuration and * need to signal when configuration should be performed - usually after * {@link #BEFORE_START_EVENT} and before {@link #START_EVENT}. */ public static final String CONFIGURE_START_EVENT = "configure_start"; /** * The LifecycleEvent type for the "configure_stop" event. Used by those * components that use a separate component to perform configuration and * need to signal when de-configuration should be performed - usually after * {@link #STOP_EVENT} and before {@link #AFTER_STOP_EVENT}. */ public static final String CONFIGURE_STOP_EVENT = "configure_stop"; // --------------------------------------------------------- Public Methods /** * Add a LifecycleEvent listener to this component. * * @param listener The listener to add */ public void addLifecycleListener(LifecycleListener listener); /** * Get the life cycle listeners associated with this life cycle. * * @return An array containing the life cycle listeners associated with this * life cycle. If this component has no listeners registered, a * zero-length array is returned. */ public LifecycleListener[] findLifecycleListeners(); /** * Remove a LifecycleEvent listener from this component. * * @param listener The listener to remove */ public void removeLifecycleListener(LifecycleListener listener); /** * Prepare the component for starting. This method should perform any * initialization required post object creation. The following * {@link LifecycleEvent}s will be fired in the following order: **
* * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ public void init() throws LifecycleException; /** * Prepare for the beginning of active use of the public methods other than * property getters/setters and life cycle methods of this component. This * method should be called before any of the public methods other than * property getters/setters and life cycle methods of this component are * utilized. The following {@link LifecycleEvent}s will be fired in the * following order: *- INIT_EVENT: On the successful completion of component * initialization.
**
* * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ public void start() throws LifecycleException; /** * Gracefully terminate the active use of the public methods other than * property getters/setters and life cycle methods of this component. Once * the STOP_EVENT is fired, the public methods other than property * getters/setters and life cycle methods should not be used. The following * {@link LifecycleEvent}s will be fired in the following order: *- BEFORE_START_EVENT: At the beginning of the method. It is as this * point the state transitions to * {@link LifecycleState#STARTING_PREP}.
*- START_EVENT: During the method once it is safe to call start() for * any child components. It is at this point that the * state transitions to {@link LifecycleState#STARTING} * and that the public methods other than property * getters/setters and life cycle methods may be * used.
*- AFTER_START_EVENT: At the end of the method, immediately before it * returns. It is at this point that the state * transitions to {@link LifecycleState#STARTED}. *
**
* * Note that if transitioning from {@link LifecycleState#FAILED} then the * three events above will be fired but the component will transition * directly from {@link LifecycleState#FAILED} to * {@link LifecycleState#STOPPING}, bypassing * {@link LifecycleState#STOPPING_PREP} * * @exception LifecycleException if this component detects a fatal error * that needs to be reported */ public void stop() throws LifecycleException; /** * Prepare to discard the object. The following {@link LifecycleEvent}s will * be fired in the following order: *- BEFORE_STOP_EVENT: At the beginning of the method. It is at this * point that the state transitions to * {@link LifecycleState#STOPPING_PREP}.
*- STOP_EVENT: During the method once it is safe to call stop() for * any child components. It is at this point that the * state transitions to {@link LifecycleState#STOPPING} * and that the public methods other than property * getters/setters and life cycle methods may no longer be * used.
*- AFTER_STOP_EVENT: At the end of the method, immediately before it * returns. It is at this point that the state * transitions to {@link LifecycleState#STOPPED}. *
**
* * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ public void destroy() throws LifecycleException; /** * Obtain the current state of the source component. * * @return The current state of the source component. */ public LifecycleState getState(); /** * Obtain a textual representation of the current component state. Useful * for JMX. The format of this string may vary between point releases and * should not be relied upon to determine component state. To determine * component state, use {@link #getState()}. * * @return The name of the current component state. */ public String getStateName(); /** * Marker interface used to indicate that the instance should only be used * once. Calling {@link #stop()} on an instance that supports this interface * will automatically call {@link #destroy()} after {@link #stop()} * completes. */ public interface SingleUse { }}- DESTROY_EVENT: On the successful completion of component * destruction.
*
主要定义事件的转态,事件的注册、注销等
lifeCycleBase
/** * Base implementation of the {@link Lifecycle} interface that implements the * state transition rules for {@link Lifecycle#start()} and * {@link Lifecycle#stop()} */public abstract class LifecycleBase implements Lifecycle { private static final Log log = LogFactory.getLog(LifecycleBase.class); private static final StringManager sm = StringManager.getManager(LifecycleBase.class); /** * The list of registered LifecycleListeners for event notifications. */ private final ListlifecycleListeners = new CopyOnWriteArrayList<>(); /** * The current state of the source component. */ private volatile LifecycleState state = LifecycleState.NEW; private boolean throwOnFailure = true; ......}
其中用到了LifecycleListener和LlifeCycleState
/** * Interface defining a listener for significant events (including "component * start" and "component stop" generated by a component that implements the * Lifecycle interface. The listener will be fired after the associated state * change has taken place. * * @author Craig R. McClanahan */public interface LifecycleListener { /** * Acknowledge the occurrence of the specified event. * * @param event LifecycleEvent that has occurred */ public void lifecycleEvent(LifecycleEvent event);}/** * The list of valid states for components that implement {@link Lifecycle}. * See {@link Lifecycle} for the state transition diagram. */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); private final boolean available; private final String lifecycleEvent; private LifecycleState(boolean available, String lifecycleEvent) { this.available = available; this.lifecycleEvent = lifecycleEvent; } /** * May the public methods other than property getters/setters and lifecycle * methods be called for a component in this state? It returns * true
for any component in any of the following states: *
- *
- {@link #STARTING} *
- {@link #STARTED} *
- {@link #STOPPING_PREP} *
true
if the component is available for use, * otherwise false
*/ public boolean isAvailable() { return available; } public String getLifecycleEvent() { return lifecycleEvent; }}/** * General event for notifying listeners of significant changes on a component * that implements the Lifecycle interface. * * @author Craig R. McClanahan */public final class LifecycleEvent extends EventObject { private static final long serialVersionUID = 1L; /** * Construct a new LifecycleEvent with the specified parameters. * * @param lifecycle Component on which this event occurred * @param type Event type (required) * @param data Event data (if any) */ public LifecycleEvent(Lifecycle lifecycle, String type, Object data) { super(lifecycle); this.type = type; this.data = data; } /** * The event data associated with this event. */ private final Object data; /** * The event type this instance represents. */ private final String type; /** * @return the event data of this event. */ public Object getData() { return data; } /** * @return the Lifecycle on which this event occurred. */ public Lifecycle getLifecycle() { return (Lifecycle) getSource(); } /** * @return the event type of this event. */ public String getType() { return this.type; }}/** * * The root class from which all event state objects shall be derived. *
* All Events are constructed with a reference to the object, the "source", * that is logically deemed to be the object upon which the Event in question * initially occurred upon. * * @since JDK1.1 */public class EventObject implements java.io.Serializable { private static final long serialVersionUID = 5516075349620653480L; /** * The object on which the Event initially occurred. */ protected transient Object source; /** * Constructs a prototypical Event. * * @param source The object on which the Event initially occurred. * @exception IllegalArgumentException if source is null. */ public EventObject(Object source) { if (source == null) throw new IllegalArgumentException("null source"); this.source = source; } /** * The object on which the Event initially occurred. * * @return The object on which the Event initially occurred. */ public Object getSource() { return source; } /** * Returns a String representation of this EventObject. * * @return A a String representation of this EventObject. */ public String toString() { return getClass().getName() + "[source=" + source + "]"; }}
注意LifecycleBase的lifecycleListeners是copyOnWriteList
@Overridepublic final synchronized void init() throws LifecycleException { if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } try { setStateInternal(LifecycleState.INITIALIZING, null, false); initInternal(); setStateInternal(LifecycleState.INITIALIZED, null, false); } catch (Throwable t) { handleSubClassException(t, "lifecycleBase.initFail", toString()); }}
init方法是个同步方法,如果state的状态不是new,会抛出LifecycleException异常
private void invalidTransition(String type) throws LifecycleException { String msg = sm.getString("lifecycleBase.invalidTransition", type, toString(), state); throw new LifecycleException(msg);}
init方法调用initInternal(),是个抽象方法,留给子类实现
init方法两次调用setStateInternal方法,这也是同步方法,由于执行init的调用者已经获得当前对象的锁,所以会调用这个方法,而不阻塞(主要作用是触发监听其事件的监听器)
private synchronized void setStateInternal(LifecycleState state, Object data, boolean check) throws LifecycleException { if (log.isDebugEnabled()) { log.debug(sm.getString("lifecycleBase.setState", this, state)); } if (check) { // Must have been triggered by one of the abstract methods (assume // code in this class is correct) // null is never a valid state if (state == null) { invalidTransition("null"); // Unreachable code - here to stop eclipse complaining about // a possible NPE further down the method return; } // Any method can transition to failed // startInternal() permits STARTING_PREP to STARTING // stopInternal() permits STOPPING_PREP to STOPPING and FAILED to // STOPPING if (!(state == LifecycleState.FAILED || (this.state == LifecycleState.STARTING_PREP && state == LifecycleState.STARTING) || (this.state == LifecycleState.STOPPING_PREP && state == LifecycleState.STOPPING) || (this.state == LifecycleState.FAILED && state == LifecycleState.STOPPING))) { // No other transition permitted invalidTransition(state.name()); } } this.state = state; String lifecycleEvent = state.getLifecycleEvent(); if (lifecycleEvent != null) { fireLifecycleEvent(lifecycleEvent, data); }}
/** * Allow sub classes to fire {@link Lifecycle} events. * * @param type Event type * @param data Data associated with event. */protected void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(this, type, data); for (LifecycleListener listener : lifecycleListeners) { listener.lifecycleEvent(event); }}
这种处理异常的方式值得学习
private void handleSubClassException(Throwable t, String key, Object... args) throws LifecycleException { ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null, false); String msg = sm.getString(key, args); if (getThrowOnFailure()) { if (!(t instanceof LifecycleException)) { t = new LifecycleException(msg, t); } throw (LifecycleException) t; } else { log.error(msg, t); }}
这是start方法
/** * {@inheritDoc} */@Overridepublic final synchronized void start() throws LifecycleException { if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) || LifecycleState.STARTED.equals(state)) { //如果正在启动中,则打印日志,return if (log.isDebugEnabled()) { Exception e = new LifecycleException(); log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e); } else if (log.isInfoEnabled()) { log.info(sm.getString("lifecycleBase.alreadyStarted", toString())); } return; } if (state.equals(LifecycleState.NEW)) { init();//如果状态是new,执行初始化 } else if (state.equals(LifecycleState.FAILED)) { stop();//如果状态是failed,执行stop } else if (!state.equals(LifecycleState.INITIALIZED) && !state.equals(LifecycleState.STOPPED)) {//如果已经初始化,或停止,抛异常 invalidTransition(Lifecycle.BEFORE_START_EVENT); } try { setStateInternal(LifecycleState.STARTING_PREP, null, false);//设置全局state startInternal(); if (state.equals(LifecycleState.FAILED)) { // This is a 'controlled' failure. The component put itself into the // FAILED state so call stop() to complete the clean-up. stop(); } else if (!state.equals(LifecycleState.STARTING)) { // Shouldn't be necessary but acts as a check that sub-classes are // doing what they are supposed to. invalidTransition(Lifecycle.AFTER_START_EVENT); } else { setStateInternal(LifecycleState.STARTED, null, false); } } catch (Throwable t) { // This is an 'uncontrolled' failure so put the component into the // FAILED state and throw an exception. handleSubClassException(t, "lifecycleBase.startFail", toString()); }}
该方法会根据state值决定调用init,stop方法,以下是stop方法
/** * {@inheritDoc} */@Overridepublic final synchronized void stop() throws LifecycleException { if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) || LifecycleState.STOPPED.equals(state)) {//如果将、正在、已经stop if (log.isDebugEnabled()) { Exception e = new LifecycleException(); log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e); } else if (log.isInfoEnabled()) { log.info(sm.getString("lifecycleBase.alreadyStopped", toString())); } return; } if (state.equals(LifecycleState.NEW)) { state = LifecycleState.STOPPED; return; } if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) { invalidTransition(Lifecycle.BEFORE_STOP_EVENT); } try { if (state.equals(LifecycleState.FAILED)) { // Don't transition to STOPPING_PREP as that would briefly mark the // component as available but do ensure the BEFORE_STOP_EVENT is // fired fireLifecycleEvent(BEFORE_STOP_EVENT, null); } else { setStateInternal(LifecycleState.STOPPING_PREP, null, false); } stopInternal(); // Shouldn't be necessary but acts as a check that sub-classes are // doing what they are supposed to. if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) { invalidTransition(Lifecycle.AFTER_STOP_EVENT); } setStateInternal(LifecycleState.STOPPED, null, false); } catch (Throwable t) { handleSubClassException(t, "lifecycleBase.stopFail", toString()); } finally { if (this instanceof Lifecycle.SingleUse) { // Complete stop process first setStateInternal(LifecycleState.STOPPED, null, false); destroy(); } }}
如果其实现了Lifecycle.SingleUse接口,会调用destroy方法(有一点疑问,在destroy()方法里也会调用stop()方法,会有问题吗)
@Overridepublic final synchronized void destroy() throws LifecycleException { if (LifecycleState.FAILED.equals(state)) { try { // Triggers clean-up stop(); } catch (LifecycleException e) { // Just log. Still want to destroy. log.warn(sm.getString( "lifecycleBase.destroyStopFail", toString()), e); } } if (LifecycleState.DESTROYING.equals(state) || LifecycleState.DESTROYED.equals(state)) { if (log.isDebugEnabled()) { Exception e = new LifecycleException(); log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e); } else if (log.isInfoEnabled() && !(this instanceof Lifecycle.SingleUse)) { // Rather than have every component that might need to call // destroy() check for SingleUse, don't log an info message if // multiple calls are made to destroy() log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString())); } return; } if (!state.equals(LifecycleState.STOPPED) && !state.equals(LifecycleState.FAILED) && !state.equals(LifecycleState.NEW) && !state.equals(LifecycleState.INITIALIZED)) { invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT); }//只有 停止ed,失败ed,初始化ed,new 可以destroy,pre ing不可以 try { setStateInternal(LifecycleState.DESTROYING, null, false); destroyInternal(); setStateInternal(LifecycleState.DESTROYED, null, false); } catch (Throwable t) { handleSubClassException(t, "lifecycleBase.destroyFail", toString()); }}
2 jmx
/** * This interface is implemented by components that will be registered with an * MBean server when they are created and unregistered when they are destroyed. * It is primarily intended to be implemented by components that implement * {@link Lifecycle} but is not exclusively for them. */public interface JmxEnabled extends MBeanRegistration { /** * @return the domain under which this component will be / has been * registered. */ String getDomain(); /** * Specify the domain under which this component should be registered. Used * with components that cannot (easily) navigate the component hierarchy to * determine the correct domain to use. * * @param domain The name of the domain under which this component should be * registered */ void setDomain(String domain); /** * @return the name under which this component has been registered with JMX. */ ObjectName getObjectName();}/** *Can be implemented by an MBean in order to * carry out operations before and after being registered or unregistered from * the MBean Server. An MBean can also implement this interface in order * to get a reference to the MBean Server and/or its name within that * MBean Server.
* 用于在mbean的注册前后、注销前后做相关操作 * @since 1.5 */public interface MBeanRegistration { /** * Allows the MBean to perform any operations it needs before * being registered in the MBean Server. If the name of the MBean * is not specified, the MBean can provide a name for its * registration. If any exception is raised, the MBean will not be * registered in the MBean Server. * * @param server The MBean Server in which the MBean will be registered. * * @param name The object name of the MBean. This name is null if * the name parameter to one of thecreateMBean
or *registerMBean
methods in the {@link MBeanServer} * interface is null. In that case, this method must return a * non-null ObjectName for the new MBean. * * @return The name under which the MBean is to be registered. * This value must not be null. If thename
* parameter is not null, it will usually but not necessarily be * the returned value. * * @exception java.lang.Exception This exception will be caught by * the MBean Server and re-thrown as an {@link * MBeanRegistrationException}. */ public ObjectName preRegister(MBeanServer server, ObjectName name) throws java.lang.Exception; /** * Allows the MBean to perform any operations needed after having been * registered in the MBean server or after the registration has failed. *If the implementation of this method throws a {@link RuntimeException} * or an {@link Error}, the MBean Server will rethrow those inside * a {@link RuntimeMBeanException} or {@link RuntimeErrorException}, * respectively. However, throwing an exception in {@code postRegister} * will not change the state of the MBean: * if the MBean was already registered ({@code registrationDone} is * {@code true}), the MBean will remain registered.
*This might be confusing for the code calling {@code createMBean()} * or {@code registerMBean()}, as such code might assume that MBean * registration has failed when such an exception is raised. * Therefore it is recommended that implementations of * {@code postRegister} do not throw Runtime Exceptions or Errors if it * can be avoided.
* @param registrationDone Indicates whether or not the MBean has * been successfully registered in the MBean server. The value * false means that the registration phase has failed. */ public void postRegister(Boolean registrationDone); /** * Allows the MBean to perform any operations it needs before * being unregistered by the MBean server. * * @exception java.lang.Exception This exception will be caught by * the MBean server and re-thrown as an {@link * MBeanRegistrationException}. */ public void preDeregister() throws java.lang.Exception ; /** * Allows the MBean to perform any operations needed after having been * unregistered in the MBean server. *If the implementation of this method throws a {@link RuntimeException} * or an {@link Error}, the MBean Server will rethrow those inside * a {@link RuntimeMBeanException} or {@link RuntimeErrorException}, * respectively. However, throwing an exception in {@code postDeregister} * will not change the state of the MBean: * the MBean was already successfully deregistered and will remain so.
*This might be confusing for the code calling * {@code unregisterMBean()}, as it might assume that MBean deregistration * has failed. Therefore it is recommended that implementations of * {@code postDeregister} do not throw Runtime Exceptions or Errors if it * can be avoided.
*/ public void postDeregister(); }
3 Registry
注册表,用于创建、操作mbean,并简化其使用,其自身也是一个mbean。以下是其全局变量
/* Issues: - exceptions - too many "throws Exception" - double check the interfaces - start removing the use of the experimental methods in tomcat, then remove the methods ( before 1.1 final ) - is the security enough to prevent Registry beeing used to avoid the permission checks in the mbean server ?*//** * Registry for modeler MBeans. * * This is the main entry point into modeler. It provides methods to create * and manipulate model mbeans and simplify their use. * * This class is itself an mbean. * * IMPORTANT: public methods not marked with @since x.x are experimental or * internal. Should not be used. * * @author Craig R. McClanahan * @author Costin Manolache */public class Registry implements RegistryMBean, MBeanRegistration { /** * The Log instance to which we will write our log messages. */ private static final Log log = LogFactory.getLog(Registry.class); // Support for the factory methods /** Will be used to isolate different apps and enhance security. * 隔离app并增强其安全性:key用来隔离,Registry.guard确保安全性 */ private static final HashMap
getRegistry 获取注册表,静态同步方法,线程安全
/** * Factory method to create (if necessary) and return our * Registry
instance. * * The current version uses a static - future versions could use * the thread class loader. * * @param key Support for application isolation. If null, the context class * loader will be used ( if setUseContextClassLoader is called ) or the * default registry is returned. key用于app隔离 * @param guard Prevent access to the registry by untrusted components 用于阻止不信任的组件访问注册表 * @return the registry * @since 1.1 */ public static synchronized Registry getRegistry(Object key, Object guard) { Registry localRegistry; if( perLoaderRegistries!=null ) { if( key==null ) key=Thread.currentThread().getContextClassLoader();//获取当前线程的classLoader if( key != null ) { localRegistry = perLoaderRegistries.get(key); if( localRegistry == null ) { localRegistry=new Registry();// localRegistry.key=key; localRegistry.guard=guard; perLoaderRegistries.put( key, localRegistry ); return localRegistry; } if( localRegistry.guard != null && localRegistry.guard != guard ) {//验证守护者 return null; // XXX Should I throw a permission ex ? } return localRegistry; } } // static if (registry == null) {//registry是静态的(单例) registry = new Registry(); } if( registry.guard != null && registry.guard != guard ) { return null; } return (registry); }
getMBeanServer 实例、同步方法 获取MBeanServer,可以看出,每个registry的MBeanServer是单例、延时加载的
/** * Factory method to create (if necessary) and return our * MBeanServer
instance. * @return the MBean server */ public synchronized MBeanServer getMBeanServer() { if (server == null) { long t1 = System.currentTimeMillis(); if (MBeanServerFactory.findMBeanServer(null).size() > 0) { server = MBeanServerFactory.findMBeanServer(null).get(0); if (log.isDebugEnabled()) { log.debug("Using existing MBeanServer " + (System.currentTimeMillis() - t1)); } } else { server = ManagementFactory.getPlatformMBeanServer(); if (log.isDebugEnabled()) { log.debug("Creating MBeanServer" + (System.currentTimeMillis() - t1)); } } } return server; }
下面方法根据给定的bean、objectName,动态生成DynamicMBean,并注册到MBeanServer
/** * Register a component * 注册组件(jmx) * @param bean The bean * @param oname The object name * @param type The registry type * @throws Exception Error registering component */ public void registerComponent(Object bean, ObjectName oname, String type) throws Exception { if( log.isDebugEnabled() ) { log.debug( "Managed= "+ oname); } if( bean ==null ) { log.error("Null component " + oname ); return; } try { if( type==null ) {//当type传null时,type=bean的类名 type=bean.getClass().getName(); } ManagedBean managed = findManagedBean(null, bean.getClass(), type); // The real mbean is created and registered DynamicMBean mbean = managed.createMBean(bean); if( getMBeanServer().isRegistered( oname )) { if( log.isDebugEnabled()) { log.debug("Unregistering existing component " + oname ); } getMBeanServer().unregisterMBean( oname ); } getMBeanServer().registerMBean( mbean, oname); } catch( Exception ex) { log.error("Error registering " + oname, ex ); throw ex; } }
4 LifecycleMBeanBase
以下是全局变量,jmx部分可参考
private static final Log log = LogFactory.getLog(LifecycleMBeanBase.class);//日志 private static final StringManager sm = StringManager.getManager("org.apache.catalina.util");//日志信息 /* Cache components of the MBean registration. */ private String domain = null;//jmx domain private ObjectName oname = null;// jmx objectName protected MBeanServer mserver = null;//jmx MBeanServer
这是initInternal方法,init方法/start方法会调用。作用是初始化MBeanServer,将当前对象转成MBean并注册到MBeanServer中。获取mserver的方法在上面,重点看register方法
/** * Sub-classes wishing to perform additional initialization should override * this method, ensuring that super.initInternal() is the first call in the * overriding method. * 子类复写本方法时,需将super.initInternal()放第一行。与jmx的注册初始化相关 */ @Override protected void initInternal() throws LifecycleException { // If oname is not null then registration has already happened via // preRegister(). if (oname == null) { mserver = Registry.getRegistry(null, null).getMBeanServer(); oname = register(this, getObjectNameKeyProperties()); } } /** * Utility method to enable sub-classes to easily register additional * components that don't implement {@link JmxEnabled} with an MBean server. * 方便子类注册组件到MBean server而不用实现JmxEabled * * Note: This method should only be used once {@link #initInternal()} has * been called and before {@link #destroyInternal()} has been called. * * @param obj The object the register 要注册的对象 * @param objectNameKeyProperties The key properties component of the objectName要用 * object name to use to register the * object * * @return The name used to register the object */ protected final ObjectName register(Object obj, String objectNameKeyProperties) { // Construct an object name with the right domain StringBuilder name = new StringBuilder(getDomain()); name.append(':'); name.append(objectNameKeyProperties); ObjectName on = null; try { on = new ObjectName(name.toString()); //根据给定的bean与ObjectName, 生成DynamicMBean, 并注册到MBeanServer Registry.getRegistry(null, null).registerComponent(obj, on, null); } catch (MalformedObjectNameException e) { log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name), e); } catch (Exception e) { log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name), e); } return on; } /** * Obtain the domain under which this component will be / has been * registered. */ @Override public final String getDomain() { if (domain == null) { domain = getDomainInternal(); } if (domain == null) { domain = Globals.DEFAULT_MBEAN_DOMAIN; } return domain; } /** * Method implemented by sub-classes to identify the domain in which MBeans * should be registered. * * @return The name of the domain to use to register MBeans. */ protected abstract String getDomainInternal();
这是destroyInternal方法
/** * 子类复写此方法时,在方法的最后 super.destroyInternal() * Sub-classes wishing to perform additional clean-up should override this * method, ensuring that super.destroyInternal() is the last call in the * overriding method. */ @Override protected void destroyInternal() throws LifecycleException { unregister(oname); } /** * Utility method to enable sub-classes to easily unregister additional * components that don't implement {@link JmxEnabled} with an MBean server. * * Note: This method should only be used once {@link #initInternal()} has * been called and before {@link #destroyInternal()} has been called. * * @param on The name of the component to unregister */ protected final void unregister(ObjectName on) { // If null ObjectName, just return without complaint if (on == null) { return; } // If the MBeanServer is null, log a warning & return if (mserver == null) { log.warn(sm.getString("lifecycleMBeanBase.unregisterNoServer", on)); return; } try { mserver.unregisterMBean(on); } catch (MBeanRegistrationException e) { log.warn(sm.getString("lifecycleMBeanBase.unregisterFail", on), e); } catch (InstanceNotFoundException e) { log.warn(sm.getString("lifecycleMBeanBase.unregisterFail", on), e); } }
这是MBeanRegistration接口方法的实现,可以指定MBeanServer, objectName, (因为在初始化时,都会先判空)
/** * Allows the object to be registered with an alternative * {@link MBeanServer} and/or {@link ObjectName}. */@Overridepublic final ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { this.mserver = server; this.oname = name; this.domain = name.getDomain(); return oname;}