20.1.2 使用接口定义 MBean 的操作和属性

Spring 的 InterfaceBasedMBeanInfoAssembler 是另一种 MBean 信息装配器,可以让我们通过使用接口来选择 bean 的哪些方法需要暴露为 MBean 的托管操作。InterfaceBasedMBeanInfoAssembler 与基于方法名称的装配器很相似,只不过不再通过罗列方法名称来确定暴露哪些方法,而是通过列出接口来声明哪些方法需要暴露。

例如,假设我们定义了一个名为 SpittleControllerManagedOperations 的接口,如下所示:

package com.habuma.spittr.jmx;

public interface SpittleControllerManagedOperations {
  int getSpittlePerPage();
  void setSpittlesPerPage(int spittlesPerPage);
}

在这里,我们选择了 setSpittlesPerPage() 方法和 getSpittlesPerPage() 方法作为需要暴露的方法。再次提醒,这 一对存取器方法间接暴露了 spittlesPerPage 属性作为 MBean 的托管属性。为了应用此装配器,我们只需要使用如下的 assembler bean 替换之前基于方法名称的装配器即可:

@Bean
public InterfaceBasedMBeanlnfoAssembler assembler() {
  InterfaceBasedMBeanlnfoAssembler assembler = new InterfaceBasedMBeanlnfoAssembler();
  assembler.setManagedlnterfaces( new Class<?>[] { SpittleControllerManagedOperations.class });
  return assembler;
}

managedInterfaces 属性接受一个或多个接口组成的列表作为 MBean 的管理接口 —— 在本示例中为 SpittleControllerManagedOperations 接口。

SpittleController 并没有显式实现 SpittleControllerManagedOperations 接口,这可能并不明显,但相当有趣。这个接口只是为了标识导出的内容,但我们并不需要在代码中直接实现该接口。不过,SpittleController 应该实现这个接口,其实也没有其他的原因,只是在 MBean 和实现类之间应该有一个一致的协议。

如果通过接口来选择 MBean 操作的话,最吸引人的一点在于我们可以把很多方法放在少量的接口中,从而确保 InterfaceBasedMBeanInfoAssembler 的配置尽量简洁。在输出多个 MBean 时,基于接口的方式可以帮助保持 Spring 配置的简洁。

最终,这些托管操作必须在某处声明,无论是在 Spring 配置中还是在某个接口中。此外,从代码角度看,托管操作的声明是一种重复 —— 在接口中或 Spring 上下文中声明的方法名称与实现中所声明的方法名称存在重复。之所以存在这种重复,没有其他原因,仅仅是为了满足 MBeanExporter 的需要而产生的。

Java 注解的一项工作就是帮助消除这种重复。让我们看看如何通过使用注解标注 Spring 管理的 bean,从而将其导出 MBean。

Last updated