Поддержка JMX (Java Management Extensions) в Spring предусматривает возможности, которые позволяют легко и прозрачно интегрировать ваше приложение Spring в инфраструктуру JMX.
В частности, поддержка JMX в Spring предусматривает четыре основные возможности:
-
Автоматическая регистрация любого бина Spring в качестве JMX MBean.
-
Гибкий механизм управления интерфейсом для контроля бинов.
-
Декларативная передача MBeans через удаленные соединители JSR-160.
-
Простое проксирование как локальных, так и удаленных MBean-ресурсов.
Данные функции предназначены для работы без привязки компонентов приложения к интерфейсам и классам Spring или JMX. Действительно, по большей части классы приложения не обязательно должны ориентироваться на Spring или JMX, чтобы была возможность пользоваться функциями JMX в Spring.
Экспорт ваших бинов в JMX
Основным классом JMX-фреймворка в Spring является MBeanExporter
. Этот класс отвечает за получение ваших бинов Spring и их регистрацию на MBeanServer
из JMX. Например, рассмотрим следующий класс:
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();
}
}
Чтобы открыть свойства и методы этого бина как атрибуты и операции MBean, можно настроить экземпляр класса MBeanExporter
в конфигурационном файле и передать в него бин, как это показано в следующем примере:
<beans>
<!-- этот бин не должен быть отложено инициализированным, если будет происходить экспорт -->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="bean:name=testBean1" value-ref="testBean"/>
</map>
</property>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
</beans>
Соответствующее определение бина из предыдущего фрагмента конфигурации – это бин exporter
. Свойство beans
указывает MBeanExporter
, какие именно ваши бины нужно экспортировать на MBeanServer
из JMX. В конфигурации по умолчанию ключ каждой записи в beans Map
используется как ObjectName
для бина, на который ссылается соответствующее значение записи.
При такой конфигурации бин testBean
отображается как MBean под именем ObjectName bean:name=testBean1
. По умолчанию все публичные свойства бина открыты как атрибуты, а все публичные методы (кроме унаследованных от класса Object
) открыты как операции.
MBeanExporter
– это бин Lifecycle
. По умолчанию MBeans экспортируются как можно позже в течение жизненного цикла приложения. Можно сконфигурировать phase
, на которой происходит экспорт, или отключить автоматическую регистрацию, установив флаг autoStartup
.Создание MBeanServer
Конфигурация, показанная в предыдущем разделе, предполагает, что приложение работает в окружении, в котором уже запущен один (и только один) MBeanServer
. В этом случае Spring пытается найти запущенный MBeanServer
и зарегистрировать ваши бины на этом сервере (если таковой имеется). Такая логика работы практична, если ваше приложение работает внутри контейнера (например, Tomcat или WebSphere от IBM), который имеет свой собственный MBeanServer
.
Однако этот подход бесполезен в автономном окружении или при запуске внутри контейнера, который не предоставляет MBeanServer
. Чтобы решить эту проблему, можно создать экземпляр MBeanServer
декларативно, добавив экземпляр класса org.springframework.jmx.support.MBeanServerFactoryBean
в вашу конфигурацию. Вы также можете обеспечить использование определенного MBeanServer
, установив значение свойства server
экземпляра MBeanExporter
в значение MBeanServer
, возвращаемое MBeanServerFactoryBean
, как показано в следующем примере:
<beans>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
<!--
этот бин должен быть предварительно инициализирован, чтобы произошел экспорт;
и это означает, что он не должен быть помечен как инициализируемый отложено
-->
<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>
В предыдущем примере экземпляр MBeanServer
создается MBeanServerFactoryBean
и передается MBeanExporter
через свойство server
. Если вы передадите собственный экземпляр MBeanServer
, MBeanExporter
не будет пытаться найти работающий MBeanServer
и использует переданный экземпляр MBeanServer
. Для того чтобы это работало правильно, нужно иметь реализацию JMX в вашем classpath.
Повторное использование существующего MBeanServer
Если сервер не задан, MBeanExporter
попытается автоматически обнаружить работающий MBeanServer
. Это работает в большинстве окружений, где используется только один экземпляр MBeanServer
. Однако, если существует несколько экземпляров, экспортер может выбрать не тот сервер. В таких случаях следует использовать MBeanServer
agentId
, чтобы указать, какой экземпляр следует использовать, как это показано в следующем примере:
<beans>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<!-- указываем, где изначально искать сервер -->
<property name="locateExistingServerIfPossible" value="true"/>
<!-- ищем экземпляр MBeanServer с заданным agentId -->
<property name="agentId" value="MBeanServer_instance_agentId>"/>
</bean>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="server" ref="mbeanServer"/>
...
</bean>
</beans>
Для платформ или случаев, где существующий MBeanServer
имеет динамический (или неизвестный) agentId
, который извлекается через методы поиска, следует использовать factory-method, как показано в следующем примере:
<beans>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="server">
<!-- Кастомный MBeanServerLocator -->
<bean class="platform.package.MBeanServerLocator" factory-method="locateMBeanServer"/>
</property>
</bean>
<!-- другие бины здесь -->
</beans>
Бины MBean с отложенной инициализацией
Если бин конфигурируется с MBeanExporter
, который также сконфигурировать на отложенную инициализацию, MBeanExporter
не нарушает этот контракт и избегает создания экземпляра бина. Вместо этого он регистрирует прокси на MBeanServer
и задерживает получение бина из контейнера до первого вызова прокси.
Автоматическая регистрация бинов MBean
Любые бины, экспортированные через MBeanExporter
и уже являющиеся действительными бинами MBean, регистрируются "как есть" на MBeanServer
без дальнейшего вмешательства со стороны Spring. Можно сделать так, чтобы MBeanExporter
автоматически обнаруживал бины MBean, установив свойство autodetect
в true
, как показано в следующем примере:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="autodetect" value="true"/>
</bean>
<bean name="spring:mbean=true" class="org.springframework.jmx.export.TestDynamicMBean"/>
В предыдущем примере бин с именем spring:mbean=true
уже является валидным JMX MBean и автоматически регистрируется Spring. По умолчанию, бин, который автоматически определен для регистрации в JMX, имеет свое собственное имя бина, используемое в качестве ObjectName
.
Управление логикой работы регистрации
Рассмотрим сценарий, в котором MBeanExporter
из Spring пытается зарегистрировать MBean
при помощи MBeanServer
, используя ObjectName bean:name=testBean1
. Если экземпляр MBean
уже был зарегистрирован под тем же ObjectName
, логика работы по умолчанию – ошибка (и генерация InstanceAlreadyExistsException
).
Можно управлять тем, что именно происходит, когда MBean
регистрируется на MBeanServer
. Поддержка JMX в Spring позволяет использовать три различных варианта логики работы при регистрации для управления логикой регистрации, если при регистрации обнаруживается, что MBean
уже был зарегистрирован под тем же ObjectName
. В следующей таблице приведена краткая информация об этих вариантах логики работы при регистрации:
Логика работы при регистрации | Пояснение |
---|---|
|
Это логика работы при регистрации по умолчанию. Если экземпляр |
|
Если экземпляр |
|
Если экземпляр |
Значения в предыдущей таблице определены как перечисляемые типы в классе RegistrationPolicy
. Если требуется изменить логику работы при регистрации по умолчанию, то нужно установить значение свойства registrationPolicy
в определении MBeanExporter
в одно из этих значений.
В следующем примере показано, как изменить логику работы при регистрации по умолчанию на логику REPLACE_EXISTING
:
<beans>
<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="registrationPolicy" value="REPLACE_EXISTING"/>
</bean>
<bean id="testBean" class="org.springframework.jmx.JmxTestBean">
<property name="name" value="TEST"/>
<property name="age" value="100"/>
</bean>
</beans>
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ