21.2.输出bean到JMX

优质
小牛编辑
133浏览
2023-12-01

21.2. 输出bean到JMX

在Spring的JMX框架中,核心类是 MBeanExporter。这个类负责获取Spring的bean,并用一个JMX MBeanServer 类来注册它们。举个例子,考虑下面的类:

package org.springframework.jmx;

public class JmxTestBean implements IJmxTestBean {

    private String name;
    private int age;
    private boolean isSuperman;

    public int getAge() {
  return age;
    }

    public void setAge(int age) {
  this.age = age;
    }
    
    public void setName(String name) {
  this.name = name;
    }

    public String getName() {
  return name;
    }

    public int add(int x, int y) {
  return x + y;
    }

    public void dontExposeMe() {
  throw new RuntimeException();
    }
}

你只需要在配置文件里简单地配置一个 MBeanExporter 的实例,并以如下所示的方法将这个bean传入,就可以将这个bean的属性和方法作为一个MBean的属性和操作暴露出去。

<beans>

  <!-- this bean must not be lazily initialized if the exporting is to happen -->
  <bean id="exporter" lazy-init="false">
    <property name="beans">
<map>
  <entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
    </property>
  </bean>

  <bean id="testBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>

</beans>

上面的配置片段中,与bean定义相关的是 exporter bean,属性 beans 是告诉类 MBeanExporter 必须将哪些bean输出到JMX的 MBeanServer 去。 缺省配置中,在 beans 中,Map 用到的每个条目的key被用做相应条目值所引用的bean的 ObjectName。 在 第 21.4 节 “控制bean的 ObjectName ” 中描述的情况下,可以改变这个行为。

在这项配置中,testBean 这个bean在 ObjectName值为 bean:name=testBean1 的情况下作为MBean暴露出去的。缺省情况下,这个bean所有的 public 的属性都作为对应MBean的属性, 这个bean所有的 public 的方法(除了那些继承自类 Object 的方法)都作为对应MBean的操作暴露出去的。

21.2.1. 创建一个MBeanServer

上述配置是假定应用程序运行在一个(仅有一个)MBeanServer 运行的环境中的。 这种情况下,Spring会试着查找运行中的 MBeanServer 并用这个server(如果有的话)来注册自己的bean。 在一个拥有自己的 MBeanServer 的容器中(如Tomcat或IBM WebSphere),这种行为是非常有用。

然而,在一个单一的环境,或运行在一个没有提供任何 MBeanServer 的容器里的情况下,这种方法毫无用处。 要处理这类问题,你可以在配置文件里添加一个类 org.springframework.jmx.support.MBeanServerFactoryBean 的实例来声明创建一个 MBeanServer 的实例。你也可以通过设置类 MBeanExporterserver 属性的值来确保使用一个特殊的 MBeanServer, 这个 MBeanServer 值是由一个 MBeanServerFactoryBean 返回的。

<beans>

  <bean id="mbeanServer"/>

  <!--
    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">
    <property name="beans">
<map>
  <entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
    </property>
    <property name="server" ref="mbeanServer"/>
  </bean>

  <bean id="testBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>

</beans>

这里,通过 MBeanServerFactoryBean 创建一个 MBeanServer 的实例,并通过属性server将这个实例提供给MBeanExporter。 在提供你自己的MBeanServer实例的时候,MBeanExporter 将不会去查找运行中的MBeanServer,而是使用这个提供的MBeanServer 实例。为了让它正确的工作,必须在你的类路径上有一个JMX的实现。

21.2.2. MBean的惰性初始化

如果你用 MBeanExporter 来配置的一个bean,同时也配置了惰性初始化,那么 MBeanExporter 不会 破坏这个约定,将避免初始化相应的bean。 而是会给 MBeanServer 注册一个代理,推迟从容器中获取这个bean,直到在代理侧发生对它的第一次调用。

21.2.3. MBean的自动注册

所有通过 MBeanExporter 输出,并已经是有效MBean的bean,会在没有Spring干涉的情况下向 MBeanServer 注册。 通过设置 autodetect 属性为 trueMBeanExporter能自动的发现MBean:

<bean id="exporter">
  <property name="autodetect" value="true"/>
</bean>

<bean name="spring:mbean=true"/>

这里,被称做 spring:mbean=true 的bean已经是一个有效的MBean了,将由Spring自动的注册。 缺省情况下,为JMX注册而自动发现的bean有它们自己的名字,用 ObjectName 来设置。 在 第 21.4 节 “控制bean的 ObjectName ” 章节里,更详细的描述了如何覆盖(override)这种行为。

21.2.4. 控制注册行为

考虑这样一个场景,一个Spring的 MBeanExporter 试着用 ObjectName 'bean:name=testBean1' 往一个 MBeanServer 里注册一个MBean。 如果之前已经有一个 MBean 实例在同一个 ObjectName 下注册了,则缺省的行为是失败(并抛出一个 InstanceAlreadyExistsException 异常)。

当向 MBeanServer 注册一个 MBean 的时候,可以控制发生哪些行为。 Spring对JMX的支持三种不同的注册行为,当注册进程找到一个已经在同一个 ObjectName 下注册过的MBean时,以此来控制注册行为。这些注册行为总结在下面的表中:

表 21.1. 注册行为

注册行为解释

REGISTRATION_FAIL_ON_EXISTING

这是缺省的注册行为。如果一个 MBean 实例已经在同一个 ObjectName 下进行注册了,则正在注册中的这个 MBean 将不会注册,同时抛出 InstanceAlreadyExistsException 异常,已经存在的 MBean 不会受到影响。

REGISTRATION_IGNORE_EXISTING

如果一个 MBean 实例已经在同一个 ObjectName 下进行注册了,正在注册的 MBean 被注册,已经存在的 MBean 不受影响,不会有 Exception 抛出。

当多个应用程序想在一个共享 MBeanServer 中共享一个公共 MBean 时,这个行为很有用。

REGISTRATION_REPLACE_EXISTING

如果一个 MBean 实例已经在同一个 ObjectName 下进行注册了,现存的已经注册过的MBean将被注销掉,新的 MBean 将代替原来的进行注册(新的 MBean 有效的替换之前的那个实例)。


上述各值(分别是 REGISTRATION_FAIL_ON_EXISTINGREGISTRATION_IGNORE_EXISTINGREGISTRATION_REPLACE_EXISTING)作为常数定义在类 MBeanRegistrationSupport 中(类 MBeanExporter 继承自这个超类)。如果你想改变缺省注册行为,只需要在你的 MBeanExporter 的定义中简单的把属性 registrationBehaviorName 设置成这些值中的一个就可以了。

下面的例子说明了如何从缺省的注册行为改变为 REGISTRATION_REPLACE_EXISTING 行为。

<beans>

    <bean id="exporter">
  <property name="beans">
<map>
    <entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
  </property>
  <property name="registrationBehaviorName" value="REGISTRATION_REPLACE_EXISTING"/>
    </bean>

    <bean id="testBean">
  <property name="name" value="TEST"/>
  <property name="age" value="100"/>
    </bean>

</beans>