Spec-Zone.ru › OpenJDK 8

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


@Documented
 @Retention(value=RUNTIME)
 @Target(value=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 MXBean
public interface MemoryPoolMBean {
    String getName();
    MemoryUsage getUsage();
    // ...
}
public interface MemoryPoolMXBean {
    String getName();
    MemoryUsage getUsage();
    // ...
}

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

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

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

Standard MBean MXBean
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() {...}
}
public class MemoryUsage {
    // standard JavaBean conventions with getters
    @ConstructorProperties({"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 (хотя это можно сделать). С другой стороны, мы добавили аннотацию @ConstructorProperties для связи параметров конструктора с соответствующими методами получения.

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

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

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

Standard MBean MXBean
String name = (String)
    mbeanServer.getAttribute(objectName, "Name");
MemoryUsage usage = (MemoryUsage)
    mbeanServer.getAttribute(objectName, "Usage");
long used = usage.getUsed();
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 MXBean
MemoryPoolMBean proxy =
    JMX.newMBeanProxy(
        mbeanServer,
        objectName,
        MemoryPoolMBean.class);
String name = proxy.getName();
MemoryUsage usage = proxy.getUsage();
long used = usage.getUsed();
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 MXBean
public class MemoryPool
        implements MemoryPoolMBean {
    public String getName() {...}
    public MemoryUsage getUsage() {...}
    // ...
}
public class MemoryPool
        implements MemoryPoolMXBean {
    public String getName() {...}
    public MemoryUsage getUsage() {...}
    // ...
}

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

Standard MBean MXBean
{
    MemoryPoolMBean pool = new MemoryPool();
    mbeanServer.registerMBean(pool, objectName);
}
{
    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>:

  • Открытый тип, 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 должны быть восстанавливаемыми.

Допускаются нулевые значения для всех типов Java и Открытых типов, за исключением примитивных типов Java, где это невозможно. При преобразовании из типа J в тип opendata(J) или из типа opendata(J) в тип J, нулевое значение отображается в нулевое значение.

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

Тип 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, и т.д. Открытый тип — это соответствующий SimpleType. Таким образом, opentype(long) — это SimpleType.LONG, а opendata(long) — это java.lang.Long.

Массив примитивного типа, например, long[], может быть представлен непосредственно как Открытый тип. Таким образом, 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().

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>, имеет Открытый тип TabularType и отображается на TabularData. У TabularType есть два элемента, называемые key и value. Открытый тип key — это opentype(K), а Открытый тип 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().

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

TabularData — это интерфейс. Конкретный класс, используемый для представления Map<K,V> в виде Открытых данных — это 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. Открытый тип для этого атрибута — 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 был зарегистрирован в двух разных ObjectNames, ссылка на этот 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 и имеет тип SimpleType.STRING. Если геттер —
boolean isName()
то элемент в CompositeType называется name и имеет тип SimpleType.BOOLEAN.

Обратите внимание, что первая буква (или код символа) преобразуется в нижний регистр. Это соответствует соглашению Java Beans, которое по историческим причинам отличается от соглашения Standard MBean. В интерфейсе Standard 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 Type 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 есть хотя бы один публичный конструктор с аннотацией ConstructorProperties, то один из этих конструкторов (не обязательно всегда тот же самый) будет вызван для восстановления экземпляра J. Каждая такая аннотация должна содержать столько строк, сколько параметров имеет конструктор; каждая строка должна называть свойство, соответствующее геттеру J; и тип этого геттера должен быть таким же, как соответствующий параметр конструктора. Не является ошибкой, если существуют геттеры, которые не упоминаются в аннотации ConstructorProperties (они могут соответствовать информации, не необходимой для восстановления объекта).

    Экземпляр J восстанавливается путем вызова конструктора с соответствующими восстановленными элементами из CompositeData. Конструктор, который будет вызван, будет определен во время выполнения на основе элементов, фактически присутствующих в CompositeData, учитывая, что этот CompositeData может исходить из более ранней версии J, где не все элементы были присутствуют. Конструктор применим, если все свойства, указанные в его аннотации 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 SE, которые не включают пакет java.beans. При нацеливании на среду выполнения, не включающую пакет 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. Публичный конструктор с аннотацией @ConstructorProperties:
    public class NamedNumber {
        public int getNumber() {return number;}
        public String getName() {return name;}
        @ConstructorProperties({"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 Server, будет пустым, если MXBean не реализует интерфейс NotificationBroadcaster. В противном случае, он будет результатом вызова NotificationBroadcaster.getNotificationInfo() в момент регистрации MXBean. Даже если результат этого метода изменится впоследствии, результат вызова MBeanInfo.getNotifications() не изменится. Список, возвращаемый для MXBean, созданного с использованием класса StandardMBean или StandardEmitterMBean, выводится аналогичным образом, как для стандартных 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), например, из String в Enum, если нет константы Enum с таким именем.

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

Since:
1.6

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

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

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

Элементы

value

public abstract boolean value

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

Returns:
true, если аннотированный интерфейс является интерфейсом 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.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API