gpt4 book ai didi

java - MXBean 操作签名中的抽象类型

转载 作者:行者123 更新时间:2023-11-30 11:11:34 27 4
gpt4 key购买 nike

我正在尝试创建一个 MXBean 操作,它将返回一个没有属性的抽象类型(实际类型及其属性将在运行时确定)。我的数据模型可以简单的表述如下:

public interface I extends CompositeDataView {
// empty
}

public final class A implements I {
private final String foo;

@ConstructorProperties({"foo"})
public A(final String foo) {/* ... */}

public String getFoo() {/* ... */}

@Override
public CompositeData toCompositeData(CompositeType ct) {/* ... */}

public static A from(final CompositeData cd) {/* ... */}
}

public final class B implements I {
private final String bar;

@ConstructorProperties({"bar"})
public B(final String bar) {/* ... */}

public String getBar() {/* ... */}

@Override
public CompositeData toCompositeData(CompositeType ct) {/* ... */}

public static B from(final CompositeData cd) {/* ... */}
}

... MXBean 操作签名是:

@MXBean
public interface Baz {
I f();
}

该操作可以返回具有 foo 属性的 A 实例,或具有 bar< 的 B 实例 属性。当然,当我尝试注册 MBean 实例时,立即会看到一个 Shiny 的 NotCompliantMBeanException:

Caused by: javax.management.openmbean.OpenDataException: Can't map I to an open data type
at com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory.makeCompositeMapping(DefaultMXBeanMappingFactory.java:458)
at com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory.makeMapping(DefaultMXBeanMappingFactory.java:292)
at com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory.mappingForType(DefaultMXBeanMappingFactory.java:257)

似乎我可以用常规 MBeanSerializable 做一些事情,但不能用 MXBeanCompositeDataView。还是我错了?

最佳答案

虽然不是那么简单,但可以或多或少地做自己想做的事。关键是 MXBean 规范要求 CompositeData 至少有一项。您可以通过在基类中添加属性 type 来满足此要求,我在这里将其称为 AnyCompositeDatatype 属性还可以用于决定如何从 CompositeData 转换回特定类型,例如您的 FooBar。在这里的代码中,我将所有内容都塞进了 AnyCompositeData 类,但更现实的是,当然它是单独的类。我只拼出了具体的类 Foo,但是如何扩展模式以支持其他类应该是显而易见的。

public abstract class AnyCompositeData implements CompositeDataView {
private final String type;

public AnyCompositeData(String type) {
this.type = type;
}

public String getType() {
return type;
}

public static AnyCompositeData from(CompositeData cd) {
switch ((String) cd.get("type")) {
case "Foo":
return new Foo((String) cd.get("foo"));
default:
throw new IllegalArgumentException("Don't know how to reconstruct: " + cd.get("type"));
}
}

public static class Foo extends AnyCompositeData {
private final String foo;

Foo(String foo) {
super("Foo");
this.foo = foo;
}

public String getFoo() {
return foo;
}

@Override
public CompositeData toCompositeData(CompositeType ct) {
try {
String[] items = {"type", "foo"};
OpenType<?>[] itemTypes = {SimpleType.STRING, SimpleType.STRING};
Object[] itemValues = {"Foo", foo};
CompositeType compositeType = new CompositeType("Foo", "Foo", items, items, itemTypes);
return new CompositeDataSupport(compositeType, items, itemValues);
} catch (OpenDataException e) {
throw new RuntimeException(e);
}
}
}

@MXBean
public interface Baz {
AnyCompositeData f();
}

static class BazImpl implements Baz {
@Override
public AnyCompositeData f() {
return new Foo("whatever");
}
}

public static void main(String[] args) throws Exception {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName objectName = new ObjectName("test:baz=baz");
mbs.registerMBean(new BazImpl(), objectName);
Baz bazProxy = JMX.newMXBeanProxy(mbs, objectName, Baz.class);
AnyCompositeData result = bazProxy.f();
assert result instanceof Foo;
assert ((Foo) result).getFoo().equals("whatever");
}
}

如果你有很多像 Foo 这样的子类,那么你可能想考虑以某种方式使用反射,而不是让 from(CompositeData) 方法知道所有子类。

关于java - MXBean 操作签名中的抽象类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27356140/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com