Тип аннотации MXBean

@Documented
@Retention(RUNTIME)
@Target(TYPE)
public @interface MXBean

Аннотация для явного обозначения интерфейса как интерфейса MXBean или как интерфейса, не являющегося MXBean. По умолчанию, интерфейс является интерфейсом MXBean, если он является публичным и его имя оканчивается на MXBean, как в SomethingMXBean. Следующие интерфейсы являются интерфейсами MXBean:

public interface WhatsitMXBean {}

    @MXBean
    public interface Whatsit1Interface {}

    @MXBean(true)
    public interface Whatsit2Interface {}

Следующие интерфейсы не являются интерфейсами MXBean:

interface NonPublicInterfaceNotMXBean{}

    public interface Whatsit3Interface{}

    @MXBean(false)
    public interface MisleadingMXBean {}

Спецификация MXBean

Концепция MXBean предоставляет простой способ кодирования MBean, который ссылается только на предопределенный набор типов, определённых в javax.management.openmbean. Таким образом, вы можете быть уверены, что ваш MBean будет пригоден для любого клиента, включая удалённых клиентов, без необходимости, чтобы клиент имел доступ к модель-специфичным классам, представляющим типы ваших MBeans.

Концепции легче понять при сравнении с концепцией Standard MBean. Вот как управляемый объект может быть представлен как Standard MBean и как MXBean:

Standard MBean

public interface MemoryPoolMBean {
    String getName();
    MemoryUsage getUsage();
    // ...
}

MXBean

public interface MemoryPoolMXBean {
    String getName();
    MemoryUsage getUsage();
    // ...
}

Как видите, определения очень похожи. Единственное отличие заключается в том, что соглашение об именовании интерфейса для MXBean использует SomethingMXBean вместо SomethingMBean для Standard MBean.

В этом управляемом объекте есть атрибут, называемый Usage типа MemoryUsage. Цель такого атрибута заключается в предоставлении согласованной «моментальной фотографии» набора элементов данных. Например, он может включать текущий объём используемой памяти в пуле памяти и текущий максимум пула памяти. Если бы эти значения были отдельными элементами, полученными с помощью отдельных вызовов getAttribute, то мы могли бы получить значения, полученные в разное время, которые не были бы согласованными. Мы могли бы получить значение used, которое было бы больше, чем значение max.

Итак, мы можем определить MemoryUsage следующим образом:

Standard MBean

public class MemoryUsage implements Serializable {
    // standard JavaBean conventions with getters

    public MemoryUsage(long init, long used,
                       long committed, long max) {...}
    long getInit() {...}
    long getUsed() {...}
    long getCommitted() {...}
    long getMax() {...}
}

MXBean

public class MemoryUsage {
    // standard JavaBean conventions with getters
    @ConstructorParameters({"init", "used", "committed", "max"})
    public MemoryUsage(long init, long used,
                       long committed, long max) {...}
    long getInit() {...}
    long getUsed() {...}
    long getCommitted() {...}
    long getMax() {...}
}

Определения одинаковы в обоих случаях, за исключением того, что для MXBean MemoryUsage больше не нужно помечать Serializable (хотя это возможно). С другой стороны, мы добавили аннотацию @ConstructorParameters для связывания параметров конструктора с соответствующими методами-геттерами. Подробнее об этом ниже.

MemoryUsage является модель-специфичным классом. В случае Standard MBeans клиент MBean Server не может получить доступ к атрибуту Usage, если не знает класс MemoryUsage. Предположим, клиент представляет собой обобщенную консоль на основе технологии JMX. Тогда консоль должна быть настроена с модель-специфичными классами каждого приложения, к которому она может подключиться. Проблема ещё больше усугубляется для клиентов, написанных не на языке Java. В таком случае может не быть способа сообщить клиенту, как выглядит MemoryUsage.

В этом случае MXBeans отличаются от Standard MBeans. Хотя мы определяем интерфейс управления практически точно так же, как и раньше, фреймворк MXBean преобразует модель-специфичные классы в стандартные классы платформы Java. Используя массивы и классы CompositeData и TabularData из стандартного пакета javax.management.openmbean, можно создать структуры данных произвольной сложности, используя только стандартные классы.

Это становится более ясным, если сравнить, как могут выглядеть клиенты обеих моделей:

Standard MBean

String name = (String)
    mbeanServer.getAttribute(objectName, "Name");
MemoryUsage usage = (MemoryUsage)
    mbeanServer.getAttribute(objectName, "Usage");
long used = usage.getUsed();

MXBean

String name = (String)
    mbeanServer.getAttribute(objectName, "Name");
CompositeData usage = (CompositeData)
    mbeanServer.getAttribute(objectName, "Usage");
long used = (Long) usage.get("used");

Для атрибутов с простыми типами, такими как String, код идентичен. Но для атрибутов со сложными типами код Standard MBean требует, чтобы клиент знал модель-специфичный класс MemoryUsage, в то время как код MXBean не требует использования нестандартных классов.

Код клиента для MXBean немного сложнее. Однако, если клиент на самом деле знает модель, здесь интерфейс MemoryPoolMXBean и класс MemoryUsage, то он может построить прокси. Это рекомендуемый способ взаимодействия с управляемыми объектами, когда модель известна заранее, независимо от того, используете ли вы Standard MBeans или MXBeans:

Standard MBean

MemoryPoolMBean proxy =
    JMX.newMBeanProxy(
        mbeanServer,
        objectName,
        MemoryPoolMBean.class);
String name = proxy.getName();
MemoryUsage usage = proxy.getUsage();
long used = usage.getUsed();

MXBean

MemoryPoolMXBean proxy =
    JMX.newMXBeanProxy(
        mbeanServer,
        objectName,
        MemoryPoolMXBean.class);
String name = proxy.getName();
MemoryUsage usage = proxy.getUsage();
long used = usage.getUsed();

Реализация объекта MemoryPool аналогична как для Standard MBeans, так и для MXBeans.

Standard MBean

public class MemoryPool
        implements MemoryPoolMBean {
    public String getName() {...}
    public MemoryUsage getUsage() {...}
    // ...
}

MXBean

public class MemoryPool
        implements MemoryPoolMXBean {
    public String getName() {...}
    public MemoryUsage getUsage() {...}
    // ...
}

Регистрация MBean в MBean Server происходит одинаково в обоих случаях:

Standard MBean

{
    MemoryPoolMBean pool = new MemoryPool();
    mbeanServer.registerMBean(pool, objectName);
}

MXBean

{
    MemoryPoolMXBean pool = new MemoryPool();
    mbeanServer.registerMBean(pool, objectName);
}

Определение MXBean

MXBean — это разновидность MBean. Объект MXBean может быть зарегистрирован непосредственно в MBean Server или использоваться в качестве аргумента для StandardMBean, а полученный MBean зарегистрирован в MBean Server.

Когда объект регистрируется в MBean Server с помощью методов registerMBean или createMBean интерфейса MBeanServer, проверяется класс объекта, чтобы определить его тип MBean:

  • Если класс реализует интерфейс DynamicMBean, то MBean является Dynamic MBean. Обратите внимание, что класс StandardMBean реализует этот интерфейс, поэтому этот случай применим к Standard MBean или MXBean, созданному с помощью класса StandardMBean.
  • В противном случае, если класс соответствует соглашениям об именовании Standard MBean, то MBean является Standard MBean.
  • В противном случае, это может быть MXBean. Проверяется набор реализованных объектом интерфейсов на предмет интерфейсов, которые:
    • имеют имя класса SMXBean (где S — любая непустая строка) и не имеют аннотации @MXBean(false); и/или
    • имеют аннотацию @MXBean(true) или просто @MXBean.
    Если существует ровно один такой интерфейс или если существует один такой интерфейс, являющийся подынтерфейсом всех остальных, то объект является MXBean. Интерфейс в вопросе — это MXBean-интерфейс. В примере выше MXBean-интерфейсом является MemoryPoolMXBean.
  • Если ни одно из этих условий не выполняется, MBean является недействительным, и попытка его регистрации вызовет NotCompliantMBeanException.

Каждый тип Java, который появляется в качестве параметра или возвращаемого значения метода в интерфейсе MXBean, должен быть преобразуем в соответствии с правилами ниже. Кроме того, параметры должны быть восстановимы, как определено ниже.

Попытка создать MXBean, не соответствующий вышеуказанным правилам, вызовет исключение.

Соглашения об именовании

К методам MXBean применяются те же соглашения об именовании, что и к методам Standard MBean:

  1. Метод T getN(), где T — тип Java (не void) и N — непустая строка, указывает на то, что существует читаемый атрибут, называемый N. Тип Java и открытый тип атрибута определяются правилами сопоставления ниже. Метод final Class getClass() унаследованный от Object игнорируется при поиске геттеров.
  2. Метод boolean isN() указывает на то, что существует читаемый атрибут, называемый N с типом Java boolean и открытым типом SimpleType.Boolean.
  3. Метод void setN(T x) указывает на то, что существует записываемый атрибут, называемый N. Тип Java и открытый тип атрибута определяются правилами сопоставления ниже. (Конечно, имя x параметра не имеет значения.)
  4. Все остальные методы указывают на то, что существует операция с тем же именем, что и метод. Тип Java и открытый тип возвращаемого значения и каждого параметра определяются правилами сопоставления ниже.

Правила для getN и isN вместе определяют понятие геттера. Правило для setN определяет понятие сеттера.

Ошибка — это наличие двух геттеров с одинаковым именем или двух сеттеров с одинаковым именем. Если есть геттер и сеттер для одного имени, то тип T в обоих случаях должен быть одинаковым. В этом случае атрибут является читаемым/записываемым. Если есть только геттер или только сеттер, атрибут является только для чтения или только для записи соответственно.

Правила сопоставления типов

MXBean — это разновидность Open MBean, как определено в пакете javax.management.openmbean. Это означает, что типы атрибутов, параметров операций и возвращаемых значений операций должны описываться с помощью открытых типов, то есть четырёх стандартных подклассов OpenType. MXBeans достигают этого, сопоставляя типы Java с открытыми типами.

Для каждого типа Java J сопоставление MXBean описывается следующей информацией:

  • Соответствующий открытый тип, opentype(J). Это экземпляр подкласса OpenType.
  • Преобразованный тип Java, opendata(J), который всегда одинаков для любого данного opentype(J). Это класс Java.
  • Как значение преобразуется из типа J в тип opendata(J).
  • Как значение преобразуется из типа opendata(J) в тип J, если это возможно.

Например, для типа Java List<String>:

  • Тип данных Open Type, opentype( List<String>), является ArrayType(1, SimpleType.STRING), представляющим одномерный массив String.
  • Сопоставленный тип Java, opendata( List<String>), это String[].
  • List<String> можно преобразовать в String[] с помощью List.toArray(new String[0]).
  • String[] можно преобразовать в List<String> с помощью Arrays.asList.

Если нет правил сопоставления для получения opentype(J) из J, то J не может быть типом параметра или возвращаемого значения метода в интерфейсе MXBean.

Если есть способ преобразовать opendata(J) обратно в J, то J называется восстанавливаемым. Все параметры методов в интерфейсе MXBean должны быть восстанавливаемыми, потому что когда среда MXBean вызывает метод, ей потребуется преобразовать эти параметры из opendata(J) в J. В прокси, сгенерированном с помощью JMX.newMXBeanProxy, именно значения, возвращаемые методами в интерфейсе MXBean, должны быть восстанавливаемыми.

Значения null разрешены для всех типов Java и типов Open Type, за исключением примитивных типов Java, где они невозможны. При преобразовании из типа J в тип opendata(J) или из типа opendata(J) в тип J, значение null сопоставляется со значением null.

В следующей таблице обобщены правила сопоставления типов.

Тип Java J opentype(J) opendata(J)
int, boolean, и т.д.
(8 примитивных типов Java)
SimpleType.INTEGER,
SimpleType.BOOLEAN, и т.д
Integer, Boolean, и т.д.
(соответствующие упакованные типы)
Integer, ObjectName, и т.д.
(типы, охватываемые SimpleType)
соответствующий SimpleType J, тот же тип
int[] и т.д.
(одномерный массив с примитивным типом элемента)
ArrayType.getPrimitiveArrayType(int[].class) и т.д J, тот же тип
E[]
(массив с не примитивным типом элемента E; это включает int[][], где E — int[])
ArrayType.getArrayType(opentype(E)) opendata(E)[]
List<E>
Set<E>
SortedSet<E> (см. ниже)
то же, что для E[] то же, что для E[]
Перечисление E
(объявлено в Java как enum E {...})
SimpleType.STRING String
Map<K,V>
SortedMap<K,V>
TabularType
(см. ниже)
TabularData
(см. ниже)
Интерфейс MXBean SimpleType.OBJECTNAME
(см. ниже)
ObjectName
(см. ниже)
Любой другой тип CompositeType, если возможно
(см. ниже)
CompositeData

В следующих разделах приведены дополнительные сведения о данных правилах.

Сопоставления для примитивных типов

8 примитивных типов Java (boolean, byte, short, int, long, float, double, char) сопоставляются с соответствующими упакованными типами из java.lang, а именно Boolean, Byte, и т.д. Тип Open Type — соответствующий SimpleType. Таким образом, opentype( long) — это SimpleType.LONG, а opendata(long) — это java.lang.Long.

Массив примитивного типа, такой как long[], может быть представлен непосредственно как тип Open Type. Таким образом, openType( long[]) — это ArrayType.getPrimitiveArrayType(long[].class), а opendata(long[]) — это long[].

На практике разница между простым int и Integer, и т.д., не проявляется, так как операции в API JMX всегда выполняются над объектами Java, а не над примитивами. Однако эта разница проявляется в массивах.

Сопоставления для коллекций (List<E> и т.д.)

List<E> или Set<E>, такие как List<String> или Set<ObjectName>, сопоставляются таким же образом, как и массив того же типа элемента, например, String[] или ObjectName[].

SortedSet<E> также сопоставляется аналогично E[], но только при условии, что E — класс или интерфейс, реализующий Comparable. Таким образом, SortedSet<String> или SortedSet<Integer> преобразуются, но SortedSet<int[]> или SortedSet<List<String>> — нет. Преобразование экземпляра SortedSet завершится ошибкой IllegalArgumentException, если его comparator() не равен null.

List<E> восстанавливается как java.util.ArrayList<E>; Set<E> как java.util.HashSet<E>; SortedSet<E> как java.util.TreeSet<E>.

Сопоставления для словарей (Map<K,V> и т.д.)

Map<K,V> или SortedMap<K,V>, например, Map<String,ObjectName>, имеет тип Open Type TabularType и сопоставляется со TabularData. TabularType содержит два элемента, называемые key и value. Тип Open Type key — opentype(K), а тип Open Type value — opentype(V). Индекс TabularType — это единственный элемент key.

Например, TabularType для Map<String,ObjectName> может быть создан кодом такого вида:

String typeName =
    "java.util.Map<java.lang.String, javax.management.ObjectName>";
String[] keyValue =
    new String[] {"key", "value"};
OpenType[] openTypes =
    new OpenType[] {SimpleType.STRING, SimpleType.OBJECTNAME};
CompositeType rowType =
    new CompositeType(typeName, typeName, keyValue, keyValue, openTypes);
TabularType tabularType =
    new TabularType(typeName, typeName, rowType, new String[] {"key"});

typeName определяется правилами именования типов, подробно описанными ниже.

SortedMap<K,V> сопоставляется аналогично, но только при условии, что K — класс или интерфейс, реализующий Comparable. Таким образом, SortedMap<String,int[]> преобразуется, но SortedMap<int[],String> — нет. Преобразование экземпляра SortedMap завершится ошибкой IllegalArgumentException, если его comparator() не равен null.

Map<K,V> восстанавливается как java.util.HashMap<K,V>; SortedMap<K,V> как java.util.TreeMap<K,V>.

TabularData — это интерфейс. Конкретный класс, используемый для представления Map<K,V> как Open Data, — TabularDataSupport или другой класс, реализующий TabularData, который сериализуется как TabularDataSupport.

Сопоставления для интерфейсов MXBean

Интерфейс MXBean или тип, на который ссылается интерфейс MXBean, может ссылаться на другой интерфейс MXBean, J. Тогда opentype(J) — SimpleType.OBJECTNAME, а opendata(J) — ObjectName.

Например, предположим, что у вас есть два интерфейса MXBean такого вида:

public interface ProductMXBean {
    public ModuleMXBean[] getModules();
}

public interface ModuleMXBean {
    public ProductMXBean getProduct();
}

Объект, реализующий интерфейс ModuleMXBean, возвращает из своего метода getProduct объект, реализующий интерфейс ProductMXBean . И объект ModuleMXBean и возвращаемые объекты ProductMXBean должны быть зарегистрированы как MXBeans в одном и том же сервере MBean.

Метод ModuleMXBean.getProduct() определяет атрибут под названием Product. Тип Open Type для этого атрибута — SimpleType.OBJECTNAME, а соответствующее значение ObjectName будет именем, под которым указанный ProductMXBean зарегистрирован в сервере MBean.

Если вы создаёте прокси MXBean для ModuleMXBean и вызываете его метод getProduct(), прокси преобразует ObjectName обратно в ProductMXBean, создав другой прокси MXBean. Более формально, когда прокси, созданный с помощью JMX.newMXBeanProxy(mbeanServerConnection, objectNameX, interfaceX), должен преобразовать objectNameY обратно в interfaceY, другой интерфейс MXBean, он делает это с помощью JMX.newMXBeanProxy(mbeanServerConnection, objectNameY, interfaceY). Реализация может вернуть прокси, который был ранее создан вызовом JMX.newMXBeanProxy с теми же параметрами, или может создать новый прокси.

Обратное преобразование показано следующей модификацией интерфейса ModuleMXBean:

public interface ModuleMXBean {
    public ProductMXBean getProduct();
    public void setProduct(ProductMXBean c);
}

Наличие метода setProduct означает, что атрибут Product теперь является читаемым и записываемым. Как и прежде, значение этого атрибута — ObjectName. При установке атрибута значение ObjectName должно быть преобразовано в объект ProductMXBean, ожидаемый методом setProduct. Этот объект будет прокси-объектом MXBean для заданного ObjectName в том же сервере MBean.

Если вы создадите прокси-объект MXBean для ModuleMXBean и вызовете его метод setProduct, прокси-объект преобразует свой аргумент ProductMXBean обратно в ObjectName. Это сработает только в том случае, если аргумент является прокси-объектом другого ProductMXBean в том же MBeanServerConnection. Прокси-объект может быть возвращен другим прокси-объектом (например, ModuleMXBean.getProduct(), который возвращает прокси-объект для ProductMXBean); или он может быть создан с помощью JMX.newMXBeanProxy; или он может быть создан с помощью Proxy с обработчиком вызовов, который является MBeanServerInvocationHandler или его подклассом.

Если один и тот же MXBean зарегистрирован в двух разных ObjectName , ссылка на этот MXBean из другого MXBean будет неоднозначной. Поэтому, если объект MXBean уже зарегистрирован в сервере MBean, и делается попытка зарегистрировать его в том же сервере MBean под другим именем, результатом будет InstanceAlreadyExistsException. В общем случае следует избегать регистрации одного и того же объекта MBean под несколькими именами, особенно потому, что это плохо работает для MBean, которые являются NotificationBroadcasters.

Сопоставления для других типов

Если Java-класс или интерфейс J не соответствует другим правилам в таблице выше, механизм MXBean попытается сопоставить его с CompositeType следующим образом. Имя типа этого CompositeType определяется правилами имен типов ниже.

Класс проверяется на наличие методов-геттеров, используя указанные выше соглашения. (Методы-геттеры должны быть публичными методами экземпляров.) Если геттеры отсутствуют или тип любого геттера не может быть преобразован, то J не может быть преобразован.

Если существует хотя бы один геттер, и тип каждого геттера может быть преобразован, то opentype(J) является CompositeType с одним элементом для каждого геттера. Если геттер является

T getName()
то элемент в CompositeType называется name и имеет тип opentype(T). Например, если элемент является
String getOwner()
то элемент называется owner и имеет тип Open SimpleType.STRING. Если геттер является
boolean isName()
то элемент в CompositeType называется name и имеет тип SimpleType.BOOLEAN.

Обратите внимание, что первая буква (или код символа) преобразуется в нижний регистр. Это соответствует соглашению Java Beans, которое по историческим причинам отличается от соглашения Standard MBean. В стандартном интерфейсе MBean или MXBean метод getOwner определяет атрибут, называемый Owner, в то время как в Java Bean или сопоставленном CompositeType, метод getOwner определяет свойство или элемент, называемый owner.

Если два метода генерируют одно и то же имя элемента (например, getOwner и isOwner, или getOwner и getowner ), то тип не может быть преобразован.

Когда Open Type равен CompositeType, соответствующий сопоставленный Java-тип (opendata(J)) — это CompositeData. Сопоставление экземпляра J с CompositeData , соответствующим описанному выше CompositeType , выполняется следующим образом. Во-первых, если J реализует интерфейс CompositeDataView, то вызывается метод toCompositeData этого интерфейса для выполнения преобразования. В противном случае CompositeData создается путем вызова геттера для каждого элемента и преобразования его в соответствующий тип Open Data. Таким образом, геттер, такой как

List<String> getNames()

будет сопоставлен с элементом с именем "names" и типом Open ArrayType(1, SimpleType.STRING). Преобразование в CompositeData будет вызывать getNames() и преобразовывать полученный List<String> в String[] для элемента "names".

CompositeData является интерфейсом. Конкретный класс, используемый для представления типа как Open Data, — это CompositeDataSupport, или другой класс, реализующий CompositeData , который сериализуется как CompositeDataSupport.

Восстановление экземпляра Java-типа J из CompositeData

Если opendata(J) является CompositeData для Java-типа J, то экземпляр J можно восстановить из CompositeData или J не может быть восстановлен. Если какой-либо элемент в CompositeData не может быть восстановлен, то J также не может быть восстановлен.

Для любого заданного J применяются следующие правила для определения способа восстановления экземпляров J из CompositeData. Будет использовано первое применимое правило в списке.

  1. Если у J есть метод
    public static J from(CompositeData cd)
    то этот метод используется для восстановления экземпляра J.

  2. В противном случае, если у J есть хотя бы один публичный конструктор с аннотацией @javax.management.ConstructorParameters или @java.beans.ConstructoProperties, то один из этих конструкторов (не обязательно всегда один и тот же) будет вызван для восстановления экземпляра J. Если конструктор помечен как @javax.management.ConstructorParameters и @java.beans.ConstructorProperties, то @javax.management.ConstructorParameters будет использоваться, а @java.beans.ConstructorProperties будет проигнорировано. В каждой такой аннотации должны быть перечислены все строки, соответствующие параметрам конструктора; каждая строка должна называть свойство, соответствующее геттеру J; и тип этого геттера должен быть таким же, как соответствующий параметр конструктора. Не является ошибкой, если существуют геттеры, которые не упомянуты в аннотациях @ConstructorParameters или @ConstructorProperties (они могут соответствовать информации, которая не требуется для восстановления объекта).

    Экземпляр J восстанавливается путем вызова конструктора с соответствующими восстановленными элементами из CompositeData. Вызываемый конструктор будет определен во время выполнения на основе элементов, фактически присутствующих в CompositeData, учитывая, что этот CompositeData может поступать из более ранней версии J, где не все элементы были присутствовать. Конструктор является применимым, если все свойства, указанные в его аннотациях @ConstructorParameters или @ConstructorProperties, присутствуют как элементы в CompositeData. Если ни один конструктор не применим, попытка восстановить J завершается неудачно.

    Для любой возможной комбинации свойств должно выполняться одно из следующих условий: (а) нет применимых конструкторов, (б) есть ровно один применимый конструктор, или (в) один из применимых конструкторов указывает на надмножество свойств, указанных каждым другим применимым конструктором. (Другими словами, никогда не должно возникать неоднозначности в выборе конструктора.) Если это условие не выполняется, то J не может быть восстановлен.

  3. В противном случае, если у J есть публичный конструктор без аргументов, и для каждого геттера в J с типом T и именем N есть соответствующий сеттер с тем же именем и типом, то экземпляр J создается с помощью конструктора без аргументов, и вызываются сеттеры со значениями, восстановленными из CompositeData для восстановления значений. Например, если есть метод
    public List<String> getNames()
    то должен быть и метод
    public void setNames(List<String> names)
    для применения этого правила.

    Если CompositeData поступает из более ранней версии J, некоторые элементы могут отсутствовать. В этом случае соответствующие сеттеры не будут вызваны.

  4. В противном случае, если J — это интерфейс, у которого нет методов, кроме геттеров, экземпляр J создается с помощью Proxy с CompositeDataInvocationHandler, поддерживаемым преобразуемым CompositeData.

  5. В противном случае, J не может быть восстановлен.

Правило 2 не применяется, когда java.beans.ConstructorProperties не виден (например, когда модуль java.desktop недоступен или когда в среде выполнения отсутствует модуль java.desktop). При работе со средой выполнения, не включающей пакет java.beans, и когда возникает несоответствие между средой компиляции и среды выполнения, в которой J скомпилирован с публичным конструктором и аннотацией ConstructorProperties, то J не может быть восстановлен, если другое правило не применяется.

Вот примеры кодирования типа NamedNumber, состоящего из int и String. В каждом случае CompositeType выглядит следующим образом:

CompositeType(
    "NamedNumber",                      // typeName
    "NamedNumber",                      // description
    new String[] {"number", "name"},    // itemNames
    new String[] {"number", "name"},    // itemDescriptions
    new OpenType[] {SimpleType.INTEGER,
                    SimpleType.STRING}  // itemTypes
);
  1. Статический from метод:
    public class NamedNumber {
        public int getNumber() {return number;}
        public String getName() {return name;}
        private NamedNumber(int number, String name) {
            this.number = number;
            this.name = name;
        }
        public static NamedNumber from(CompositeData cd) {
            return new NamedNumber((Integer) cd.get("number"),
                                   (String) cd.get("name"));
        }
        private final int number;
        private final String name;
    }
  2. Публичный конструктор с аннотацией @ConstructorParameters :
    public class NamedNumber {
        public int getNumber() {return number;}
        public String getName() {return name;}
        @ConstructorParameters({"number", "name"})
        public NamedNumber(int number, String name) {
            this.number = number;
            this.name = name;
        }
        private final int number;
        private final String name;
    }
  3. Сеттер для каждого геттера:
    public class NamedNumber {
        public int getNumber() {return number;}
        public void setNumber(int number) {this.number = number;}
        public String getName() {return name;}
        public void setName(String name) {this.name = name;}
        public NamedNumber() {}
        private int number;
        private String name;
    }
  4. Интерфейс только с геттерами:
    public interface NamedNumber {
        public int getNumber();
        public String getName();
    }

Чаще всего для классов, которые просто представляют собой набор данных, лучше использовать неизменяемость. Экземпляр неизменяемого класса не может быть изменен после его создания. Обратите внимание, что сам CompositeData является неизменяемым. Неизменяемость имеет много преимуществ, особенно с точки зрения безопасности и потокобезопасности. Поэтому подход, использующий сеттеры, следует избегать, если это возможно.

Рекурсивные типы

Рекурсивные (самоссылочные) типы не могут использоваться в интерфейсах MXBean. Это следствие неизменяемости CompositeType. Например, следующий тип не может быть типом атрибута, потому что он ссылается на себя:

public interface Node {
    public String getName();
    public int getPriority();
    public Node getNext();
}

Всегда возможно переписать рекурсивные типы таким образом, чтобы они больше не были рекурсивными. Для этого может потребоваться введение новых типов. Например:

public interface NodeList {
    public List<Node> getNodes();
}

public interface Node {
    public String getName();
    public int getPriority();
}

Содержание MBeanInfo для MXBean

MXBean — это тип Open MBean. Однако по соображениям совместимости его MBeanInfo не является OpenMBeanInfo. В частности, когда тип атрибута, параметра или возвращаемого значения операции является примитивным типом, таким как int, или является void (для типа возвращаемого значения), то атрибут, параметр или операция будут представлены соответственно MBeanAttributeInfo, MBeanParameterInfo или MBeanOperationInfo, чьи getType() или getReturnType() возвращают имя примитивного типа ("int" и т.д.). Это так даже несмотря на то, что правила сопоставления выше указывают, что сопоставление opendata — это обернутый тип (Integer и т.д.).

Массив публичных конструкторов, возвращаемый MBeanInfo.getConstructors() для MXBean, который зарегистрирован непосредственно в сервере MBean, будет содержать все публичные конструкторы этого MXBean. Если класс MXBean не является публичным, то и его конструкторы также не считаются публичными. Список, возвращаемый для MXBean, созданного с использованием класса StandardMBean, выводится аналогичным образом, как для Standard MBean. Независимо от того, как был создан MXBean, параметры его конструктора не подлежат правилам сопоставления MXBean и не имеют соответствующего OpenType.

Массив типов уведомлений, возвращаемый MBeanInfo.getNotifications() для MXBean, который зарегистрирован непосредственно в сервере MBean, будет пустым, если MXBean не реализует интерфейс NotificationBroadcaster. В противном случае, он будет результатом вызова NotificationBroadcaster.getNotificationInfo() в момент регистрации MXBean. Даже если результат этого метода изменится впоследствии, результат MBeanInfo.getNotifications() не изменится. Список, возвращаемый для MXBean, созданного с использованием класса StandardMBean или StandardEmitterMBean, выводится аналогичным образом, как для Standard MBean.

Описание Descriptor для всех MBeanAttributeInfo, MBeanParameterInfo и MBeanOperationInfo объектов, содержащихся в MBeanInfo , будет иметь поле openType, значение которого — OpenType, заданный правилами сопоставления выше. Так, даже когда getType() равно "int", getDescriptor().getField("openType") будет SimpleType.INTEGER.

Для каждого из этих объектов Descriptor также будет иметь поле originalType , которое является строкой, представляющей тип Java, появившийся в интерфейсе MXBean. Формат этой строки описан в разделе Имена типов ниже.

Для Descriptor для MBeanInfo будет поле mxbean со значением строки "true".

Имена типов

Иногда неотображенный тип T параметра или возвращаемого значения метода в MXBean должен быть представлен в виде строки. Если T — это тип без дженериков, эта строка — значение, возвращаемое Class.getName(). В противном случае, это значение genericstring(T), определенное следующим образом:

  • Если T — это непараметризованный тип без массивов, genericstring(T) — это значение, возвращаемое Class.getName(), например "int" или "java.lang.String".
  • Если T — массив E[], genericstring(T) — это genericstring(E), за которым следует "[]". Например, genericstring(int[]) — это "int[]", а genericstring( List<String>[][]) — это "java.util.List<java.lang.String>[][]".
  • В противном случае T — это параметризованный тип, например List<String>, и genericstring(T) состоит из следующего: полное имя параметризованного типа, возвращаемое Class.getName(); левая угловая скобка ( "<"); genericstring(A), где A — первый параметр типа; если есть второй параметр типа B, то ", " (запятая и пробел) за которым следует genericstring(B); правая угловая скобка (">").

Обратите внимание, что если метод возвращает int[], это будет представлено строкой "[I", возвращаемой Class.getName(), но если метод возвращает List<int[]>, это будет представлено строкой "java.util.List<int[]>".

Исключения

Ошибка при сопоставлении из типов Java в типы Open сигнализируется с помощью OpenDataException. Это может произойти при анализе интерфейса MXBean, например, если он ссылается на тип, подобный java.util.Random, у которого нет геттеров. Или это может произойти при преобразовании экземпляра (возвращаемое значение метода в MXBean или параметр метода в прокси MXBean), например, при преобразовании из SortedSet<String> в String[] если у SortedSet есть ненулевой Comparator.

Ошибка при сопоставлении в типы Java из типов Open сигнализируется с помощью InvalidObjectException. Это может произойти при анализе интерфейса MXBean, например, если он ссылается на тип, который не является восстановимым в соответствии с правилами выше в контексте, где требуется восстанавливаемый тип. Или это может произойти при преобразовании экземпляра (параметр метода в MXBean или возвращаемое значение метода в прокси MXBean), например, из строки в перечисление, если нет константы перечисления с таким именем.

В зависимости от контекста OpenDataException или InvalidObjectException могут быть обернуты в другой исключение, например, RuntimeMBeanException или UndeclaredThrowableException. Для каждого сгенерированного исключения условие C будет истинным: «e является OpenDataException или InvalidObjectException (соответственно) или C истинно для e.getCause()».

Since:
1.6

Дополнительные элементы

Модификатор и тип Дополнительный элемент Описание
boolean value

Истинно, если аннотированный интерфейс является интерфейсом MXBean.

Элементы

value

boolean value

Истинно, если аннотированный интерфейс является интерфейсом MXBean.

Returns:
истина, если аннотированный интерфейс является интерфейсом MXBean.
Default:
true

© 1993, 2020, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/11/docs/api/java.management/javax/management/MXBean.html

Spec-Zone .ru
спецификации, руководства, описания, API