spring源码分析之spring jmx
JMX架构定义:
https://docs.oracle.com/javase/8/docs/technotes/guides/jmx/overview/architecture.html
Architecture Outline
JMX technology is defined by two closely related specifications developed through the Java Community Process (JCP) as Java Specification Request (JSR) 3 and JSR 160:
- JSR 3, Java Management Extensions Instrumentation and Agent Specification
- JSR 160, Java Management Extensions Remote API
The following table shows that the management architecture can be broken down into three levels. The first two levels shown in the table, instrumentation and agent,
Java VM are defined by JSR 3. The remote management level is defined by JSR 160.
Level
|
Description
|
---|---|
Instrumentation
|
Resources, such as applications, devices, or services, are instrumented using Java objects called Managed Beans (MBeans). MBeans expose their management interfaces, composed of attributes and operations, through a JMX agent for remote management and monitoring.
|
Agent
|
The main component of a JMX agent is the MBean server. This is a core managed object server in which MBeans are registered. A JMX agent also includes a set of services for handling MBeans. JMX agents directly control resources and make them available to remote management agents.
|
Remote Management
|
Protocol adaptors and standard connectors make a JMX agent accessible from remote management applications outside the agent’s Java Virtual Machine (Java VM).
|
为了更好的理解,架构图如下:
简单的结构如下所示:
spring中的集成
Spring’s JMX support provides four core features:
- The automatic registration of any Spring bean as a JMX MBean
- A flexible mechanism for controlling the management interface of your beans
- The declarative exposure of MBeans over remote, JSR-160 connectors
- The simple proxying of both local and remote MBean resources
用例:
<beans> <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/> <!--
this bean needs to be eagerly pre-instantiated in order for the exporting to occur;
this means that it must not be marked as lazily initialized
-->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="beans">
<map>
<entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
</property>
<property name="server" ref="mbeanServer"/>
</bean> <bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean> </beans>
主要实现类
MBeanServerFactoryBean创建MBeanServer
/**
* Creates the {@code MBeanServer} instance.
*/
@Override
public void afterPropertiesSet() throws MBeanServerNotFoundException {
// Try to locate existing MBeanServer, if desired.
if (this.locateExistingServerIfPossible || this.agentId != null) {
try {
this.server = locateMBeanServer(this.agentId);
}
catch (MBeanServerNotFoundException ex) {
// If agentId was specified, we were only supposed to locate that
// specific MBeanServer; so let's bail if we can't find it.
if (this.agentId != null) {
throw ex;
}
logger.info("No existing MBeanServer found - creating new one");
}
} // Create a new MBeanServer and register it, if desired.
if (this.server == null) {
this.server = createMBeanServer(this.defaultDomain, this.registerWithFactory);
this.newlyRegistered = this.registerWithFactory;
}
}
创建使用java自带的方式
/**
* Create a new {@code MBeanServer} instance and register it with the
* {@code MBeanServerFactory}, if desired.
* @param defaultDomain the default domain, or {@code null} if none
* @param registerWithFactory whether to register the {@code MBeanServer}
* with the {@code MBeanServerFactory}
* @see javax.management.MBeanServerFactory#createMBeanServer
* @see javax.management.MBeanServerFactory#newMBeanServer
*/
protected MBeanServer createMBeanServer(String defaultDomain, boolean registerWithFactory) {
if (registerWithFactory) {
return MBeanServerFactory.createMBeanServer(defaultDomain);
}
else {
return MBeanServerFactory.newMBeanServer(defaultDomain);
}
}
MBeanExporter暴露beans到MBeanServer
/**
* Kick off bean registration automatically when deployed in an {@code ApplicationContext}.
* @see #registerBeans()
*/
@Override
public void afterPropertiesSet() {
// If no server was provided then try to find one. This is useful in an environment
// where there is already an MBeanServer loaded.
if (this.server == null) {
this.server = JmxUtils.locateMBeanServer();
} try {
logger.info("Registering beans for JMX exposure on startup");
registerBeans();
registerNotificationListeners();
}
catch (RuntimeException ex) {
// Unregister beans already registered by this exporter.
unregisterNotificationListeners();
unregisterBeans();
throw ex;
}
}
注册的代码如下
//---------------------------------------------------------------------
// Exporter implementation
//--------------------------------------------------------------------- /**
* Registers the defined beans with the {@link MBeanServer}.
* <p>Each bean is exposed to the {@code MBeanServer} via a
* {@code ModelMBean}. The actual implemetation of the
* {@code ModelMBean} interface used depends on the implementation of
* the {@code ModelMBeanProvider} interface that is configured. By
* default the {@code RequiredModelMBean} class that is supplied with
* all JMX implementations is used.
* <p>The management interface produced for each bean is dependent on the
* {@code MBeanInfoAssembler} implementation being used. The
* {@code ObjectName} given to each bean is dependent on the
* implementation of the {@code ObjectNamingStrategy} interface being used.
*/
protected void registerBeans() {
// The beans property may be null, for example if we are relying solely on autodetection.
if (this.beans == null) {
this.beans = new HashMap<String, Object>();
// Use AUTODETECT_ALL as default in no beans specified explicitly.
if (this.autodetectMode == null) {
this.autodetectMode = AUTODETECT_ALL;
}
} // Perform autodetection, if desired.
int mode = (this.autodetectMode != null ? this.autodetectMode : AUTODETECT_NONE);
if (mode != AUTODETECT_NONE) {
if (this.beanFactory == null) {
throw new MBeanExportException("Cannot autodetect MBeans if not running in a BeanFactory");
}
if (mode == AUTODETECT_MBEAN || mode == AUTODETECT_ALL) {
// Autodetect any beans that are already MBeans.
logger.debug("Autodetecting user-defined JMX MBeans");
autodetectMBeans();
}
// Allow the assembler a chance to vote for bean inclusion.
if ((mode == AUTODETECT_ASSEMBLER || mode == AUTODETECT_ALL) &&
this.assembler instanceof AutodetectCapableMBeanInfoAssembler) {
autodetectBeans((AutodetectCapableMBeanInfoAssembler) this.assembler);
}
} if (!this.beans.isEmpty()) {
for (Map.Entry<String, Object> entry : this.beans.entrySet()) {
registerBeanNameOrInstance(entry.getValue(), entry.getKey());
}
}
}
继续
/**
* Registers an individual bean with the {@link #setServer MBeanServer}.
* <p>This method is responsible for deciding <strong>how</strong> a bean
* should be exposed to the {@code MBeanServer}. Specifically, if the
* supplied {@code mapValue} is the name of a bean that is configured
* for lazy initialization, then a proxy to the resource is registered with
* the {@code MBeanServer} so that the the lazy load behavior is
* honored. If the bean is already an MBean then it will be registered
* directly with the {@code MBeanServer} without any intervention. For
* all other beans or bean names, the resource itself is registered with
* the {@code MBeanServer} directly.
* @param mapValue the value configured for this bean in the beans map;
* may be either the {@code String} name of a bean, or the bean itself
* @param beanKey the key associated with this bean in the beans map
* @return the {@code ObjectName} under which the resource was registered
* @throws MBeanExportException if the export failed
* @see #setBeans
* @see #registerBeanInstance
* @see #registerLazyInit
*/
protected ObjectName registerBeanNameOrInstance(Object mapValue, String beanKey) throws MBeanExportException {
try {
if (mapValue instanceof String) {
// Bean name pointing to a potentially lazy-init bean in the factory.
if (this.beanFactory == null) {
throw new MBeanExportException("Cannot resolve bean names if not running in a BeanFactory");
}
String beanName = (String) mapValue;
if (isBeanDefinitionLazyInit(this.beanFactory, beanName)) {
ObjectName objectName = registerLazyInit(beanName, beanKey);
replaceNotificationListenerBeanNameKeysIfNecessary(beanName, objectName);
return objectName;
}
else {
Object bean = this.beanFactory.getBean(beanName);
ObjectName objectName = registerBeanInstance(bean, beanKey);
replaceNotificationListenerBeanNameKeysIfNecessary(beanName, objectName);
return objectName;
}
}
else {
// Plain bean instance -> register it directly.
if (this.beanFactory != null) {
Map<String, ?> beansOfSameType =
this.beanFactory.getBeansOfType(mapValue.getClass(), false, this.allowEagerInit);
for (Map.Entry<String, ?> entry : beansOfSameType.entrySet()) {
if (entry.getValue() == mapValue) {
String beanName = entry.getKey();
ObjectName objectName = registerBeanInstance(mapValue, beanKey);
replaceNotificationListenerBeanNameKeysIfNecessary(beanName, objectName);
return objectName;
}
}
}
return registerBeanInstance(mapValue, beanKey);
}
}
catch (Exception ex) {
throw new UnableToRegisterMBeanException(
"Unable to register MBean [" + mapValue + "] with key '" + beanKey + "'", ex);
}
}
继续
/**
* Registers an existing MBean or an MBean adapter for a plain bean
* with the {@code MBeanServer}.
* @param bean the bean to register, either an MBean or a plain bean
* @param beanKey the key associated with this bean in the beans map
* @return the {@code ObjectName} under which the bean was registered
* with the {@code MBeanServer}
*/
private ObjectName registerBeanInstance(Object bean, String beanKey) throws JMException {
ObjectName objectName = getObjectName(bean, beanKey);
Object mbeanToExpose = null;
if (isMBean(bean.getClass())) {
mbeanToExpose = bean;
}
else {
DynamicMBean adaptedBean = adaptMBeanIfPossible(bean);
if (adaptedBean != null) {
mbeanToExpose = adaptedBean;
}
}
if (mbeanToExpose != null) {
if (logger.isInfoEnabled()) {
logger.info("Located MBean '" + beanKey + "': registering with JMX server as MBean [" +
objectName + "]");
}
doRegister(mbeanToExpose, objectName);
}
else {
if (logger.isInfoEnabled()) {
logger.info("Located managed bean '" + beanKey + "': registering with JMX server as MBean [" +
objectName + "]");
}
ModelMBean mbean = createAndConfigureMBean(bean, beanKey);
doRegister(mbean, objectName);
injectNotificationPublisherIfNecessary(bean, mbean, objectName);
}
return objectName;
}
继续
/**
* Actually register the MBean with the server. The behavior when encountering
* an existing MBean can be configured using the {@link #setRegistrationBehavior(int)}
* and {@link #setRegistrationBehaviorName(String)} methods.
* @param mbean the MBean instance
* @param objectName the suggested ObjectName for the MBean
* @throws JMException if the registration failed
*/
protected void doRegister(Object mbean, ObjectName objectName) throws JMException {
ObjectName actualObjectName; synchronized (this.registeredBeans) {
ObjectInstance registeredBean = null;
try {
registeredBean = this.server.registerMBean(mbean, objectName);
}
catch (InstanceAlreadyExistsException ex) {
if (this.registrationPolicy == RegistrationPolicy.IGNORE_EXISTING) {
if (logger.isDebugEnabled()) {
logger.debug("Ignoring existing MBean at [" + objectName + "]");
}
}
else if (this.registrationPolicy == RegistrationPolicy.REPLACE_EXISTING) {
try {
if (logger.isDebugEnabled()) {
logger.debug("Replacing existing MBean at [" + objectName + "]");
}
this.server.unregisterMBean(objectName);
registeredBean = this.server.registerMBean(mbean, objectName);
}
catch (InstanceNotFoundException ex2) {
logger.error("Unable to replace existing MBean at [" + objectName + "]", ex2);
throw ex;
}
}
else {
throw ex;
}
} // Track registration and notify listeners.
actualObjectName = (registeredBean != null ? registeredBean.getObjectName() : null);
if (actualObjectName == null) {
actualObjectName = objectName;
}
this.registeredBeans.add(actualObjectName);
} onRegister(actualObjectName, mbean);
}
注册监听器
/**
* Called when an MBean is registered. Notifies all registered
* {@link MBeanExporterListener MBeanExporterListeners} of the registration event.
* <p>Please note that if an {@link MBeanExporterListener} throws a (runtime)
* exception when notified, this will essentially interrupt the notification process
* and any remaining listeners that have yet to be notified will not (obviously)
* receive the {@link MBeanExporterListener#mbeanRegistered(javax.management.ObjectName)}
* callback.
* @param objectName the {@code ObjectName} of the registered MBean
*/
@Override
protected void onRegister(ObjectName objectName) {
notifyListenersOfRegistration(objectName);
}
继续
/**
* Notifies all registered {@link MBeanExporterListener MBeanExporterListeners} of the
* registration of the MBean identified by the supplied {@link ObjectName}.
*/
private void notifyListenersOfRegistration(ObjectName objectName) {
if (this.listeners != null) {
for (MBeanExporterListener listener : this.listeners) {
listener.mbeanRegistered(objectName);
}
}
}
MBeanExporterListener
/**
* A listener that allows application code to be notified when an MBean is
* registered and unregistered via an {@link MBeanExporter}.
*
* @author Rob Harrop
* @since 1.2.2
* @see org.springframework.jmx.export.MBeanExporter#setListeners
*/
public interface MBeanExporterListener { /**
* Called by {@link MBeanExporter} after an MBean has been <i>successfully</i>
* registered with an {@link javax.management.MBeanServer}.
* @param objectName the {@code ObjectName} of the registered MBean
*/
void mbeanRegistered(ObjectName objectName); /**
* Called by {@link MBeanExporter} after an MBean has been <i>successfully</i>
* unregistered from an {@link javax.management.MBeanServer}.
* @param objectName the {@code ObjectName} of the unregistered MBean
*/
void mbeanUnregistered(ObjectName objectName); }
The MBeanProxyFactoryBean
can create a proxy to any MBean that is accessible via an MBeanServerConnection
. By default, the local MBeanServer
is located and used, but you can override this and provide an MBeanServerConnection
pointing to a remote MBeanServer
to cater for proxies pointing to remote MBeans:
<bean id="clientConnector"
class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
<property name="serviceUrl" value="service:jmx:rmi://remotehost:9875"/>
</bean> <bean id="proxy" class="org.springframework.jmx.access.MBeanProxyFactoryBean">
<property name="objectName" value="bean:name=testBean"/>
<property name="proxyInterface" value="org.springframework.jmx.IJmxTestBean"/>
<property name="server" ref="clientConnector"/>
</bean>
MBeanProxyFactoryBean
/**
* Creates a proxy to a managed resource running either locally or remotely.
* The "proxyInterface" property defines the interface that the generated
* proxy is supposed to implement. This interface should define methods and
* properties that correspond to operations and attributes in the management
* interface of the resource you wish to proxy.
*
* <p>There is no need for the managed resource to implement the proxy interface,
* although you may find it convenient to do. It is not required that every
* operation and attribute in the management interface is matched by a
* corresponding property or method in the proxy interface.
*
* <p>Attempting to invoke or access any method or property on the proxy
* interface that does not correspond to the management interface will lead
* to an {@code InvalidInvocationException}.
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.2
* @see MBeanClientInterceptor
* @see InvalidInvocationException
*/
代理实现
/**
* Checks that the {@code proxyInterface} has been specified and then
* generates the proxy for the target MBean.
*/
@Override
public void afterPropertiesSet() throws MBeanServerNotFoundException, MBeanInfoRetrievalException {
super.afterPropertiesSet(); if (this.proxyInterface == null) {
this.proxyInterface = getManagementInterface();
if (this.proxyInterface == null) {
throw new IllegalArgumentException("Property 'proxyInterface' or 'managementInterface' is required");
}
}
else {
if (getManagementInterface() == null) {
setManagementInterface(this.proxyInterface);
}
}
this.mbeanProxy = new ProxyFactory(this.proxyInterface, this).getProxy(this.beanClassLoader);
}
实现了MBeanClientInterceptor
/**
* {@link org.aopalliance.intercept.MethodInterceptor} that routes calls to an
* MBean running on the supplied {@code MBeanServerConnection}.
* Works for both local and remote {@code MBeanServerConnection}s.
*
* <p>By default, the {@code MBeanClientInterceptor} will connect to the
* {@code MBeanServer} and cache MBean metadata at startup. This can
* be undesirable when running against a remote {@code MBeanServer}
* that may not be running when the application starts. Through setting the
* {@link #setConnectOnStartup(boolean) connectOnStartup} property to "false",
* you can defer this process until the first invocation against the proxy.
*
* <p>This functionality is usually used through {@link MBeanProxyFactoryBean}.
* See the javadoc of that class for more information.
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.2
* @see MBeanProxyFactoryBean
* @see #setConnectOnStartup
*/
连接过程
/**
* Prepares the {@code MBeanServerConnection} if the "connectOnStartup"
* is turned on (which it is by default).
*/
@Override
public void afterPropertiesSet() {
if (this.server != null && this.refreshOnConnectFailure) {
throw new IllegalArgumentException("'refreshOnConnectFailure' does not work when setting " +
"a 'server' reference. Prefer 'serviceUrl' etc instead.");
}
if (this.connectOnStartup) {
prepare();
}
} /**
* Ensures that an {@code MBeanServerConnection} is configured and attempts
* to detect a local connection if one is not supplied.
*/
public void prepare() {
synchronized (this.preparationMonitor) {
if (this.server != null) {
this.serverToUse = this.server;
}
else {
this.serverToUse = null;
this.serverToUse = this.connector.connect(this.serviceUrl, this.environment, this.agentId);
}
this.invocationHandler = null;
if (this.useStrictCasing) {
// Use the JDK's own MBeanServerInvocationHandler,
// in particular for native MXBean support on Java 6.
if (JmxUtils.isMXBeanSupportAvailable()) {
this.invocationHandler =
new MBeanServerInvocationHandler(this.serverToUse, this.objectName,
(this.managementInterface != null && JMX.isMXBeanInterface(this.managementInterface)));
}
else {
this.invocationHandler = new MBeanServerInvocationHandler(this.serverToUse, this.objectName);
}
}
else {
// Non-strict casing can only be achieved through custom
// invocation handling. Only partial MXBean support available!
retrieveMBeanInfo();
}
}
}
/**
* Loads the management interface info for the configured MBean into the caches.
* This information is used by the proxy when determining whether an invocation matches
* a valid operation or attribute on the management interface of the managed resource.
*/
private void retrieveMBeanInfo() throws MBeanInfoRetrievalException {
try {
MBeanInfo info = this.serverToUse.getMBeanInfo(this.objectName); MBeanAttributeInfo[] attributeInfo = info.getAttributes();
this.allowedAttributes = new HashMap<String, MBeanAttributeInfo>(attributeInfo.length);
for (MBeanAttributeInfo infoEle : attributeInfo) {
this.allowedAttributes.put(infoEle.getName(), infoEle);
} MBeanOperationInfo[] operationInfo = info.getOperations();
this.allowedOperations = new HashMap<MethodCacheKey, MBeanOperationInfo>(operationInfo.length);
for (MBeanOperationInfo infoEle : operationInfo) {
Class<?>[] paramTypes = JmxUtils.parameterInfoToTypes(infoEle.getSignature(), this.beanClassLoader);
this.allowedOperations.put(new MethodCacheKey(infoEle.getName(), paramTypes), infoEle);
}
}
catch (ClassNotFoundException ex) {
throw new MBeanInfoRetrievalException("Unable to locate class specified in method signature", ex);
}
catch (IntrospectionException ex) {
throw new MBeanInfoRetrievalException("Unable to obtain MBean info for bean [" + this.objectName + "]", ex);
}
catch (InstanceNotFoundException ex) {
// if we are this far this shouldn't happen, but...
throw new MBeanInfoRetrievalException("Unable to obtain MBean info for bean [" + this.objectName +
"]: it is likely that this bean was unregistered during the proxy creation process",
ex);
}
catch (ReflectionException ex) {
throw new MBeanInfoRetrievalException("Unable to read MBean info for bean [ " + this.objectName + "]", ex);
}
catch (IOException ex) {
throw new MBeanInfoRetrievalException("An IOException occurred when communicating with the " +
"MBeanServer. It is likely that you are communicating with a remote MBeanServer. " +
"Check the inner exception for exact details.", ex);
}
}
javax.management.MBeanServerInvocationHandler
/**
* <p>Return a proxy that implements the given interface by
* forwarding its methods through the given MBean server to the
* named MBean. As of 1.6, the methods {@link
* JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class)} and
* {@link JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class,
* boolean)} are preferred to this method.</p>
*
* <p>This method is equivalent to {@link Proxy#newProxyInstance
* Proxy.newProxyInstance}<code>(interfaceClass.getClassLoader(),
* interfaces, handler)</code>. Here <code>handler</code> is the
* result of {@link #MBeanServerInvocationHandler new
* MBeanServerInvocationHandler(connection, objectName)}, and
* <code>interfaces</code> is an array that has one element if
* <code>notificationBroadcaster</code> is false and two if it is
* true. The first element of <code>interfaces</code> is
* <code>interfaceClass</code> and the second, if present, is
* <code>NotificationEmitter.class</code>.
*
* @param connection the MBean server to forward to.
* @param objectName the name of the MBean within
* <code>connection</code> to forward to.
* @param interfaceClass the management interface that the MBean
* exports, which will also be implemented by the returned proxy.
* @param notificationBroadcaster make the returned proxy
* implement {@link NotificationEmitter} by forwarding its methods
* via <code>connection</code>. A call to {@link
* NotificationBroadcaster#addNotificationListener} on the proxy will
* result in a call to {@link
* MBeanServerConnection#addNotificationListener(ObjectName,
* NotificationListener, NotificationFilter, Object)}, and likewise
* for the other methods of {@link NotificationBroadcaster} and {@link
* NotificationEmitter}.
*
* @param <T> allows the compiler to know that if the {@code
* interfaceClass} parameter is {@code MyMBean.class}, for example,
* then the return type is {@code MyMBean}.
*
* @return the new proxy instance.
*
* @see JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class)
*/
public static <T> T newProxyInstance(MBeanServerConnection connection,
ObjectName objectName,
Class<T> interfaceClass,
boolean notificationBroadcaster) {
final InvocationHandler handler =
new MBeanServerInvocationHandler(connection, objectName);
final Class[] interfaces;
if (notificationBroadcaster) {
interfaces =
new Class[] {interfaceClass, NotificationEmitter.class};
} else
interfaces = new Class[] {interfaceClass}; Object proxy =
Proxy.newProxyInstance(interfaceClass.getClassLoader(),
interfaces,
handler);
return interfaceClass.cast(proxy);
} public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
final Class methodClass = method.getDeclaringClass(); if (methodClass.equals(NotificationBroadcaster.class)
|| methodClass.equals(NotificationEmitter.class))
return invokeBroadcasterMethod(proxy, method, args); // local or not: equals, toString, hashCode
if (shouldDoLocally(proxy, method))
return doLocally(proxy, method, args); try {
if (isMXBean) {
MXBeanProxy p = findMXBeanProxy(methodClass);
return p.invoke(connection, objectName, method, args);
} else {
final String methodName = method.getName();
final Class[] paramTypes = method.getParameterTypes();
final Class returnType = method.getReturnType(); /* Inexplicably, InvocationHandler specifies that args is null
when the method takes no arguments rather than a
zero-length array. */
final int nargs = (args == null) ? 0 : args.length; if (methodName.startsWith("get")
&& methodName.length() > 3
&& nargs == 0
&& !returnType.equals(Void.TYPE)) {
return connection.getAttribute(objectName,
methodName.substring(3));
} if (methodName.startsWith("is")
&& methodName.length() > 2
&& nargs == 0
&& (returnType.equals(Boolean.TYPE)
|| returnType.equals(Boolean.class))) {
return connection.getAttribute(objectName,
methodName.substring(2));
} if (methodName.startsWith("set")
&& methodName.length() > 3
&& nargs == 1
&& returnType.equals(Void.TYPE)) {
Attribute attr = new Attribute(methodName.substring(3), args[0]);
connection.setAttribute(objectName, attr);
return null;
} final String[] signature = new String[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++)
signature[i] = paramTypes[i].getName();
return connection.invoke(objectName, methodName,
args, signature);
}
} catch (MBeanException e) {
throw e.getTargetException();
} catch (RuntimeMBeanException re) {
throw re.getTargetException();
} catch (RuntimeErrorException rre) {
throw rre.getTargetError();
}
/* The invoke may fail because it can't get to the MBean, with
one of the these exceptions declared by
MBeanServerConnection.invoke:
- RemoteException: can't talk to MBeanServer;
- InstanceNotFoundException: objectName is not registered;
- ReflectionException: objectName is registered but does not
have the method being invoked.
In all of these cases, the exception will be wrapped by the
proxy mechanism in an UndeclaredThrowableException unless
it happens to be declared in the "throws" clause of the
method being invoked on the proxy.
*/
}
参考文献:http://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/html/jmx.html
spring源码分析之spring jmx的更多相关文章
- Spring源码分析:Spring IOC容器初始化
概述: Spring 对于Java 开发来说,以及算得上非常基础并且核心的框架了,在有一定开发经验后,阅读源码能更好的提高我们的编码能力并且让我们对其更加理解.俗话说知己知彼,百战不殆.当你对Spri ...
- 【spring源码分析】spring ioc容器之前生今世--DefaultListableBeanFactory源码解读
spring Ioc容器的实现,从根源上是beanfactory,但真正可以作为一个可以独立使用的ioc容器还是DefaultListableBeanFactory,因此可以这么说, DefaultL ...
- spring源码分析之spring注解@Aspect是如何工作的?
1.@Aspect 在xml定义:<aop:aspectj-autoproxy />,其定义在http://www.springframework.org/schema/aop/sprin ...
- 【spring源码分析】spring关于循环依赖的问题
引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下Spring是如果解决循环依赖的. 第一种: ...
- 【spring源码分析】spring和@PostConstruct注解
@PostConstruct注解好多人以为是Spring提供的.其实是Java自己的注解. Java中该注解的说明:@PostConstruct该注解被用来修饰一个非静态的void()方法.被@Pos ...
- 【spring源码分析】spring AspectJ的Execution表达式
在使用spring框架配置AOP的时候,不管是通过XML配置文件还是注解的方式都需要定义pointcut"切入点" 例如定义切入点表达式 execution (* com.sam ...
- Spring源码分析专题——目录
Spring源码分析专题 -- 阅读指引 IOC容器 Spring源码分析专题 -- IOC容器启动过程(上篇) Spring源码分析专题 -- IOC容器启动过程(中篇) Spring源码分析专题 ...
- 【spring源码分析】IOC容器初始化——查漏补缺(一)
前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...
- spring源码分析之spring-core总结篇
1.spring-core概览 spring-core是spring框架的基石,它为spring框架提供了基础的支持. spring-core从源码上看,分为6个package,分别是asm,cgli ...
随机推荐
- 如何去掉底部的织梦版权信息powered by dedecms
由于织梦DEDECMS程序6月份的漏洞,很多织梦网站都被黑了,所以大家都在抓紧时间更新系统补丁.但是这次的DEDECMS V5.7版本更新后,在前台网页底部会出现织梦版权信息 “powered by ...
- 解决ie8(及其以下)不支持getElementsByClassName的问题
这篇技术笔记与大家分享的是:解决IE8(及以下)不支持getElementsByClassName的方法.如果有说错的地方,麻烦留言告诉我,我及时更正,一来是更新一下我的认知,二来也是不要误导的他人, ...
- Visual Studio Xamarin编译Android项目出错的解决办法
安装完Xamarin后,编译Android项目时,你会发现好长时间进度都不动,当你取消编译后,会发现其实是出错了,就是因在Android项目在第一次编译时要去google网站上下一个andorid s ...
- 【vscode】如何在vscode 中配置:TypeScript开发node环境
入门流程,大神绕行. 安装环境 这就不多说了,安装开发的环境. 安装vscode 下载地址:https://code.visualstudio.com/ 安装Nodejs 下载地址:https://n ...
- Async and Await 异步和等待
[第一次这么耐下性子认真写博客,虽然觉得很认真了,当毕竟是第一次嘛,以后再看肯定觉得很不咋滴的,更何况园子里有那么多的高人和大侠,这篇文章就权当练练手了,熟悉一下用客户端发表博客了,也希望大家多多照顾 ...
- 打造自己的视频会议系统 GGMeeting(附送源码)
自从在博客园发布广域网即时通信系统GG(QQ高仿版)以来,结识了很多做IM的朋友,然后我和我的伙伴们也接到了很多与IM相关的项目.相比在发布GG之前难以接到项目的状况相比,现在简直太幸福了,虽然做项目 ...
- Demystifying ASP.NET MVC 5 Error Pages and Error Logging
出处:http://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging Error pages and error ...
- Java设计模式12:装饰器模式
装饰器模式 装饰器模式又称为包装(Wrapper)模式.装饰器模式以多客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰器模式的结构 通常给对象添加功能,要么直接修改对象添加相应的功能, ...
- 十分钟搞定CSS选择器
在最近的web开发中是不是就会用到一些选择器,发现很多尤其是CSS3新增的不太熟悉,在此总结一下. 优先级 不同级别 1. 在属性后面使用 !important 会覆盖页面内任何位置定义的元素样式. ...
- 一则线上MySql连接异常的排查过程
Mysql作为一个常用数据库,在互联网系统应用很多.有些故障是其自身的bug,有些则不是,这里以前段时间遇到的问题举例. 问题 当时遇到的症状是这样的,我们的应用在线上测试环境,JMeter测试过程中 ...