简体   繁体   English

如何使自定义Spring MBeanExporter在候选类上使用@ Managed…批注

[英]How to make custom Spring MBeanExporter use the @Managed… annotations on a candidate class

I've written a custom Spring MBeanExporter that takes a collection of pre-created objects and creates the mbeans for them. 我编写了一个自定义的Spring MBeanExporter,它接受了一组预先创建的对象,并为它们创建了mbean。 It apparently uses the "default" strategy for determining attributes and operations, just taking the existing properties and operations of the associated class. 显然,它仅使用“默认”策略来确定属性和操作,而只是采用关联类的现有属性和操作。

I just have an "afterPropertiesSet()" method that does some work, populates the base "beans" list, and then calls its superclass method. 我只是有一个“ afterPropertiesSet()”方法,该方法可以完成一些工作,填充基本的“ beans”列表,然后调用其超类方法。 This works reasonably well. 这工作得很好。

I now want to see if I can get it to utilize any "@Managed..." annotations on the associated class. 现在,我想看看是否可以利用它在关联的类上使用任何“ @Managed ...”注释。 For my first try, I simply put the expected annotations on the associated class without changing how the "beans" list is populated and processed. 对于我的第一次尝试,我只是将期望的注释放在关联的类上,而不更改“ beans”列表的填充和处理方式。 Unfortunately, this didn't work. 不幸的是,这没有用。 I added several "description" attributes to the class, attributes, and operations, but these didn't show up in VisualVM. 我在类,属性和操作中添加了几个“描述”属性,但是这些未在VisualVM中显示。

Is there something I can do to make the MBeanExporter mechanism use the @Managed... annotations on the associated class? 我可以做些什么使MBeanExporter机制在关联的类上使用@Managed ...批注吗?

Note that my current class extends MBeanExporter. 请注意,当前类扩展了MBeanExporter。 If I change it to extend AnnotationMBeanExporter, then it fails on the classes that do NOT have @Managed... annotations. 如果将其更改为扩展AnnotationMBeanExporter,则在没有@Managed ...批注的类上它将失败。 I need something that defaults to what "MBeanExporter" does, unless it finds @Managed... annotations in a class. 我需要默认为“ MBeanExporter”的内容,除非它在类中找到@Managed ...批注。

I guess I need to show some code, but this will be mostly just pseudocode. 我想我需要显示一些代码,但这主要只是伪代码。

My MBeanExporter looks something like this: 我的MBeanExporter看起来像这样:

public class MyMBeanExporter extends MBeanExporter {

@Override
public void afterPropertiesSet() {
    // Do some pre-work to determine the list of beans to use.
    Map<String, Object> beans   = new HashMap<String, Object>();
    ... stuff
    setBeans(beans);

    // Now let the superclass create mbeans for all of the beans we found.
    super.afterPropertiesSet();
}

One of the beans that gets put into the list has a class that looks like this: 放入列表中的一个bean具有一个类似于以下的类:

@ManagedResource(objectName = ":name=fancystuff", description = "This is some stuff")
public class Stuff {
    private int howMuchStuff;

    @ManagedAttribute(description = "This tells us how much stuff we have")
    public int getHowMuchStuff() { return howMuchStuff; }

    public void setHowMuchStuff(int howMuchStuff) { this.howMuchStuff = howMuchStuff; }

    @ManagedOperation(description = "Use this to add more stuff")
    public void makeSomeMoreStuff(int stuffToAdd) {
        howMuchStuff    += stuffToAdd;
    }
}

When this gets rendered in VisualVM, none of the metadata described in the @Managed... annotations is used. 在VisualVM中呈现此内容时,不会使用@Managed ...批注中描述的任何元数据。 I can tell this for certain because the resulting ObjectName isn't the overriding value that I specified in the "@ManagedResource" annotation. 我可以肯定地说出来,因为生成的ObjectName不是我在“ @ManagedResource”注释中指定的覆盖值。

If I instead change the base class to "AnnotationMBeanExporter", then the bean associated with this class does get the metadata that I specified in the annotations. 如果我改为将基类更改为“ AnnotationMBeanExporter”,则与此类关联的Bean确实会获得我在注释中指定的元数据。 However, all the other beans that are associated with classes that do NOT have a "@ManagedResource" annotation all fail with exceptions like this: 但是,与没有“ @ManagedResource”注释的类关联的所有其他Bean都将失败,并出现以下异常:

InvalidMetadataException: No ManagedResource attribute found for class: class ...

My temporary workaround is simply to define my MBeanExporter subclass so it can behave as either a plain MBeanExporter or an AnnotationMBeanExporter, depending on a constructor flag. 我的临时解决方法是简单地定义我的MBeanExporter子类,以便根据构造函数标志,它可以充当纯MBeanExporter或AnnotationMBeanExporter。 Then, I can simply define two instances of it, one with the flag, and one without, and with a different set of paths to process. 然后,我可以简单地定义它的两个实例,一个带有标志,另一个不带标志,并带有不同的处理路径集。 This works. 这可行。

My next thing to try is to have a single "fake" MBeanExporter that internally manages an MBeanExporter and an AnnotationMBeanExporter. 我接下来要尝试的是拥有一个内部管理MBeanExporter和AnnotationMBeanExporter的单个“伪” MBeanExporter。 It will build the initial beans list, but then process each one, looking at the class associated with the bean to see if the @ManagedResource annotation is present. 它将构建初始bean列表,然后处理每个bean列表,查看与bean关联的类,以查看是否存在@ManagedResource批注。 That will indicate whether it will end up in the list of beans to be processed by the AnnotationMBeanExporter or the regular one. 这将表明它最终将出现在要由AnnotationMBeanExporter还是常规对象处理的bean列表中。

Update: I've hit a problem with this strategy, as I can't just create a raw AnnotationMBeanExporter and call "afterPropertiesSet()" on it. 更新:我遇到了这种策略的问题,因为我不能只创建一个原始的AnnotationMBeanExporter并在其上调用“ afterPropertiesSet()”。 It fails with: 它失败并显示:

MBeanExportException: Cannot autodetect MBeans if not running in a BeanFactory

Ok, I think I have something that works now. 好的,我想我现在有一些可行的方法。 I'm not sure whether this is all correct. 我不确定这是否正确。 As Martin described, I created new "assembler" and "naming strategy" classes that combine the behavior of the "default" and "annotation" variations, such that if the class in scope has a "ManagedResource" annotation, then it uses the behavior from MetadataMBeanInfoAssembler & MetadataNamingStrategy, otherwise SimpleReflectiveMBeanInfoAssembler & KeyNamingStrategy. 如Martin所述,我创建了新的“汇编程序”和“命名策略”类,它们结合了“默认”和“注释”变体的行为,因此,如果作用域中的类具有“ ManagedResource”注释,则它将使用该行为来自MetadataMBeanInfoAssembler&MetadataNamingStrategy,否则为SimpleReflectiveMBeanInfoAssembler&KeyNamingStrategy。

The implementation of the "naming strategy" subclass was somewhat simple, but the "assembler" implementation was a little more annoying because I simply had to copy the body of all the methods in MetadataMBeanInfoAssembler that were overridden and insert them in a wrapper check for the class annotation. “命名策略”子类的实现有些简单,但是“汇编器”的实现却有些烦人,因为我只需要复制MetadataMBeanInfoAssembler中所有被重写的方法的主体,然后将它们插入包装检查中即可。类注释。 There was no way to simply have an embedded "MetadataMBeanInfoAssembler" and call methods on it. 无法简单地拥有一个嵌入式“ MetadataMBeanInfoAssembler”并在其上调用方法。

Here is my "naming strategy" subclass (I could use some hints on how to get code samples to cleanly display in here): 这是我的“命名策略”子类(我可以使用一些提示,了解如何使代码示例清晰地显示在此处):

package <packagepath>.mbeans;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.metadata.JmxAttributeSource;
import org.springframework.jmx.export.naming.KeyNamingStrategy;
import org.springframework.jmx.export.naming.MetadataNamingStrategy;
import org.springframework.jmx.export.naming.ObjectNamingStrategy;

public class MetadataOrKeyNamingStrategy implements ObjectNamingStrategy, InitializingBean {
private MetadataNamingStrategy  metadataNamingStrategy  = new MetadataNamingStrategy();
private KeyNamingStrategy       keyNamingStrategy       = new KeyNamingStrategy();

public MetadataOrKeyNamingStrategy(JmxAttributeSource attributeSource) {
    metadataNamingStrategy.setAttributeSource(attributeSource);
}

@Override
public void afterPropertiesSet() throws Exception {
    metadataNamingStrategy.afterPropertiesSet();
    keyNamingStrategy.afterPropertiesSet();
}

/**
 * Specify the default domain to be used for generating ObjectNames
 * when no source-level metadata has been specified.
 * <p>The default is to use the domain specified in the bean name
 * (if the bean name follows the JMX ObjectName syntax); else,
 * the package name of the managed bean class.
 */
public void setDefaultDomain(String defaultDomain) {
    metadataNamingStrategy.setDefaultDomain(defaultDomain);
}

@Override
public ObjectName getObjectName(Object managedBean, String beanKey)
    throws MalformedObjectNameException {
    Class<?> managedClass = AopUtils.getTargetClass(managedBean);
    if (managedClass.getAnnotation(ManagedResource.class) != null)
    return metadataNamingStrategy.getObjectName(managedBean, beanKey);
    return keyNamingStrategy.getObjectName(managedBean, beanKey);
}
}

Here is the "assembler" subclass: 这是“汇编程序”子类:

package <packagepath>.mbeans;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

import javax.management.JMException;

import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.assembler.AbstractConfigurableMBeanInfoAssembler;
import org.springframework.jmx.export.metadata.JmxAttributeSource;
import org.springframework.jmx.export.metadata.ManagedAttribute;
import org.springframework.jmx.export.metadata.ManagedMetric;
import org.springframework.jmx.export.metadata.ManagedOperation;
import org.springframework.util.StringUtils;

public class MetadataOrSimpleReflectiveMBeanInfoAssembler extends AbstractConfigurableMBeanInfoAssembler {

private JmxAttributeSource                  attributeSource;

public MetadataOrSimpleReflectiveMBeanInfoAssembler() { }

public MetadataOrSimpleReflectiveMBeanInfoAssembler(JmxAttributeSource attributeSource) {
    this.attributeSource    = attributeSource;
}

@Override
protected boolean includeReadAttribute(Method method, String beanKey) {
    if (method.getDeclaringClass().getAnnotation(ManagedResource.class) != null)
    return hasManagedAttribute(method) || hasManagedMetric(method);
    return true;
}

@Override
protected boolean includeWriteAttribute(Method method, String beanKey) {
    if (method.getDeclaringClass().getAnnotation(ManagedResource.class) != null)
    return hasManagedAttribute(method);
    return true;
}

@Override
protected boolean includeOperation(Method method, String beanKey) {
    if (method.getDeclaringClass().getAnnotation(ManagedResource.class) != null) {
    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
    if (pd != null) {
        if(hasManagedAttribute(method)) {
        return true;
        }
    }
    return hasManagedOperation(method);
    }
    return true;
}

/**
 * Checks to see if the given Method has the {@code ManagedAttribute} attribute.
 */
private boolean hasManagedAttribute(Method method) {
    return (attributeSource.getManagedAttribute(method) != null);
}

/**
 * Checks to see if the given Method has the {@code ManagedMetric} attribute.
 */
private boolean hasManagedMetric(Method method) {
    return (this.attributeSource.getManagedMetric(method) != null);
}

/**
 * Checks to see if the given Method has the {@code ManagedOperation} attribute.
 * @param method the method to check
 */
private boolean hasManagedOperation(Method method) {
    return (this.attributeSource.getManagedOperation(method) != null);
}

@Override
protected void checkManagedBean(Object managedBean) throws IllegalArgumentException {
    if (managedBean.getClass().getAnnotation(ManagedResource.class) != null) {
    if (AopUtils.isJdkDynamicProxy(managedBean)) {
        throw new IllegalArgumentException(
            "MetadataMBeanInfoAssembler does not support JDK dynamic proxies - " +
            "export the target beans directly or use CGLIB proxies instead");
    }
    }
}

@Override
protected String getDescription(Object managedBean, String beanKey) throws JMException {
    if (managedBean.getClass().getAnnotation(ManagedResource.class) != null) {
    org.springframework.jmx.export.metadata.ManagedResource mr = this.attributeSource.getManagedResource(getClassToExpose(managedBean));
    return (mr != null ? mr.getDescription() : "");
    }
    else
    return super.getDescription(managedBean, beanKey);
}

@Override
protected String getAttributeDescription(PropertyDescriptor propertyDescriptor, String beanKey) {
    Method readMethod = propertyDescriptor.getReadMethod();
    if (readMethod != null && readMethod.getDeclaringClass().getAnnotation(ManagedResource.class) != null) {
    Method writeMethod = propertyDescriptor.getWriteMethod();

    ManagedAttribute getter =
        (readMethod != null ? this.attributeSource.getManagedAttribute(readMethod) : null);
    ManagedAttribute setter =
        (writeMethod != null ? this.attributeSource.getManagedAttribute(writeMethod) : null);

    if (getter != null && StringUtils.hasText(getter.getDescription())) {
        return getter.getDescription();
    }
    else if (setter != null && StringUtils.hasText(setter.getDescription())) {
        return setter.getDescription();
    }

    ManagedMetric metric = (readMethod != null ? this.attributeSource.getManagedMetric(readMethod) : null);
    if (metric != null && StringUtils.hasText(metric.getDescription())) {
        return metric.getDescription();
    }

    return propertyDescriptor.getDisplayName();

    }
    else
    return super.getAttributeDescription(propertyDescriptor, beanKey);
}

@Override
protected String getOperationDescription(Method method, String beanKey) {
    if (method.getDeclaringClass().getAnnotation(ManagedResource.class) != null) {
    PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method);
    if (pd != null) {
        ManagedAttribute ma = this.attributeSource.getManagedAttribute(method);
        if (ma != null && StringUtils.hasText(ma.getDescription())) {
        return ma.getDescription();
        }
        ManagedMetric metric = this.attributeSource.getManagedMetric(method);
        if (metric != null && StringUtils.hasText(metric.getDescription())) {
        return metric.getDescription();
        }
        return method.getName();
    }
    else {
        ManagedOperation mo = this.attributeSource.getManagedOperation(method);
        if (mo != null && StringUtils.hasText(mo.getDescription())) {
        return mo.getDescription();
        }
        return method.getName();
    }
    }
    else
    return super.getOperationDescription(method, beanKey);
}

}

I should define a reusable "AnnotationOrDefaultMBeanExporter", and then subclass that, but I'm presently using this from a custom MBeanExporter subclass, with these relevant pieces: 我应该定义一个可重用的“ AnnotationOrDefaultMBeanExporter”,然后对该子类进行子类化,但是目前我正在自定义MBeanExporter子类中使用此子类,并具有以下相关内容:

Instance variables: 实例变量:

private AnnotationJmxAttributeSource annotationSource = new AnnotationJmxAttributeSource();
private MetadataOrKeyNamingStrategy  metadataOrKeyNamingStrategy = new MetadataOrKeyNamingStrategy(annotationSource);
private MetadataOrSimpleReflectiveMBeanInfoAssembler    metadataOrSimpleReflectiveMBeanInfoAssembler    =
        new MetadataOrSimpleReflectiveMBeanInfoAssembler(annotationSource);

Constructor body: 构造器主体:

setNamingStrategy(metadataOrKeyNamingStrategy);
setAssembler(metadataOrSimpleReflectiveMBeanInfoAssembler);
setAutodetectMode(AUTODETECT_ALL);

And then: 接着:

public void setDefaultDomain(String defaultDomain) {
    this.metadataOrKeyNamingStrategy.setDefaultDomain(defaultDomain);
}

@Override
public void setBeanFactory(BeanFactory beanFactory) {
    super.setBeanFactory(beanFactory);
    this.annotationSource.setBeanFactory(beanFactory);
}

@Override
public void afterPropertiesSet() {
    // Find some beans that should be registered
    setBeans(beans);

    // Now let the superclass create mbeans for all of the beans we found.
    super.afterPropertiesSet();
}

I could use some ideas that might possibly simplify this. 我可以使用一些可能简化此方法的想法。

Ok, here's another stab at this. 好的,这是另外一个刺路。 I didn't like the fact that I ended up having to copy method bodies from either of the two alternative implementations. 我不喜欢这样的事实,我最终不得不从两个替代实现中的任何一个复制方法主体。 I concluded that I could reduce this copying if I made both the "strategy" and "assembler" custom classes be subclasses of the "metadata" versions. 我得出的结论是,如果将“策略”和“汇编器”自定义类都设为“元数据”版本的子类,则可以减少这种复制。 The basic idea is that after checking for the existence of the "@ManagedResource" annotation on the class, I can either call the superclass method, or inline the "non-metadata" version, which in all cases was less code than in the "metadata" version. 基本思想是,在检查类上是否存在“ @ManagedResource”注释后,我可以调用超类方法,也可以内联“非元数据”版本,在所有情况下,该版本的代码都比“元数据”版本。

In the case of the "strategy" class, since the relevant method in the "non-metadata" version was public, I could still create a local instance of the "strategy" class and just call the relevant method, instead of inlining the method body. 在“策略”类的情况下,由于“非元数据”版本中的相关方法是公共的,因此我仍然可以创建“策略”类的本地实例,仅调用相关方法,而不是内联该方法身体。

For the "assembler" class, I found that I didn't have to copy the bodies of any methods in the "metadata" version, but I found that I had to override additional methods, and I did have to copy in the method body of one method in the "super super class" because I can't access that directly. 对于“汇编程序”类,我发现我不必复制“元数据”版本中的任何方法的主体,但是我发现我必须重写其他方法,并且确实必须在方法主体中进行复制“超级超类”中的一种方法,因为我无法直接访问它。 The resulting class is a little shorter than my first try, so I suppose it's better, even with those slightly gnarly bits. 生成的类比我的第一次尝试要短一些,所以我想它会更好一些,即使有一点点粗糙。

To fully clean this up, this would have to be integrated into Spring to allow for the best refactoring. 为了彻底清理,必须将其集成到Spring中以实现最佳重构。 The functionality that this provides seems like a good thing to have, so I'll file a ticket to at least ask for this, and I'll post these classes in the ticket. 这样做提供的功能似乎是一件好事,因此我将提交一个票证至少要求这样做,并将这些类张贴在票证中。

In this version, I fully refactored the implementation into a "AnnotationOrDefaultMBeanExporter" class, and then my actual application-specific class extends that (which I don't need to show here). 在此版本中,我将实现完全重构为“ AnnotationOrDefaultMBeanExporter”类,然后我的实际特定于应用程序的类对此进行了扩展(在此无需显示)。

Here's the main exporter class: 这是主要的出口商类别:

package <package>;

import java.util.logging.Logger;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.jmx.export.MBeanExporter;
import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource;
import org.springframework.jmx.export.naming.MetadataNamingStrategy;

public class AnnotationOrDefaultMBeanExporter extends MBeanExporter {

protected static Logger logger = Logger.getLogger(AnnotationOrDefaultMBeanExporter.class.getName());
private AnnotationJmxAttributeSource annotationSource = new AnnotationJmxAttributeSource();
protected MetadataOrKeyNamingStrategy metadataOrKeyNamingStrategy = new MetadataOrKeyNamingStrategy(annotationSource);
protected MetadataOrSimpleReflectiveMBeanInfoAssembler metadataOrSimpleReflectiveMBeanInfoAssembler = new MetadataOrSimpleReflectiveMBeanInfoAssembler(annotationSource);

public AnnotationOrDefaultMBeanExporter() {
    setNamingStrategy(metadataOrKeyNamingStrategy);
    setAssembler(metadataOrSimpleReflectiveMBeanInfoAssembler);
    setAutodetectMode(AUTODETECT_ALL);
}

/**
 * Specify the default domain to be used for generating ObjectNames
 * when no source-level metadata has been specified.
 * <p>The default is to use the domain specified in the bean name
 * (if the bean name follows the JMX ObjectName syntax); else,
 * the package name of the managed bean class.
 * @see MetadataNamingStrategy#setDefaultDomain
 */
public void setDefaultDomain(String defaultDomain) {
    this.metadataOrKeyNamingStrategy.setDefaultDomain(defaultDomain);
}

@Override
public void setBeanFactory(BeanFactory beanFactory) {
    super.setBeanFactory(beanFactory);
    this.annotationSource.setBeanFactory(beanFactory);
}
}

Following this is the "strategy" class. 紧随其后的是“战略”课。 The somewhat gnarly bit here is wrapping a checked exception with throwing a RuntimeException(). 有点令人讨厌的地方是抛出RuntimeException()来包装检查过的异常。

package <package>;

import java.io.IOException;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.springframework.aop.support.AopUtils;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.metadata.JmxAttributeSource;
import org.springframework.jmx.export.naming.KeyNamingStrategy;
import org.springframework.jmx.export.naming.MetadataNamingStrategy;

public class MetadataOrKeyNamingStrategy extends MetadataNamingStrategy {
private KeyNamingStrategy       keyNamingStrategy       = new KeyNamingStrategy();

public MetadataOrKeyNamingStrategy() { }

public MetadataOrKeyNamingStrategy(JmxAttributeSource attributeSource) {
    super(attributeSource);
}

@Override
public void afterPropertiesSet() {
    super.afterPropertiesSet();
    try {
    keyNamingStrategy.afterPropertiesSet();
    }
    catch (IOException ex) {
    throw new RuntimeException(ex);
    }
}

@Override
public ObjectName getObjectName(Object managedBean, String beanKey)
    throws MalformedObjectNameException {
    Class<?> managedClass = AopUtils.getTargetClass(managedBean);
    if (managedClass.getAnnotation(ManagedResource.class) != null)
    return super.getObjectName(managedBean, beanKey);
    return keyNamingStrategy.getObjectName(managedBean, beanKey);
}
}

And here's the "assembler" class: 这是“汇编程序”类:

package <package>;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

import javax.management.Descriptor;

import org.springframework.aop.support.AopUtils;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler;
import org.springframework.jmx.export.metadata.JmxAttributeSource;

public class MetadataOrSimpleReflectiveMBeanInfoAssembler extends MetadataMBeanInfoAssembler {

public MetadataOrSimpleReflectiveMBeanInfoAssembler() { }

public MetadataOrSimpleReflectiveMBeanInfoAssembler(JmxAttributeSource attributeSource) {
    super(attributeSource);
}

@Override
protected boolean includeReadAttribute(Method method, String beanKey) {
    if (method.getDeclaringClass().getAnnotation(ManagedResource.class) != null)
    return super.includeReadAttribute(method, beanKey);
    return true;
}

@Override
protected boolean includeWriteAttribute(Method method, String beanKey) {
    if (method.getDeclaringClass().getAnnotation(ManagedResource.class) != null)
    return super.includeWriteAttribute(method, beanKey);
    return true;
}

@Override
protected boolean includeOperation(Method method, String beanKey) {
    if (method.getDeclaringClass().getAnnotation(ManagedResource.class) != null)
    return super.includeOperation(method, beanKey);
    return true;
}

@Override
protected String getDescription(Object managedBean, String beanKey) {
    if (managedBean.getClass().getAnnotation(ManagedResource.class) != null)
    return super.getDescription(managedBean, beanKey);
    return superSuperGetDescription(managedBean, beanKey);
}

/** Copied from AbstractMBeanInfoAssembler.getDescription(), the super.superclass of this class, which can't be easily called. */
private String superSuperGetDescription(Object managedBean, String beanKey) {
    String targetClassName = getTargetClass(managedBean).getName();
    if (AopUtils.isAopProxy(managedBean)) {
    return "Proxy for " + targetClassName;
    }
    return targetClassName;
}

@Override
protected String getAttributeDescription(PropertyDescriptor propertyDescriptor, String beanKey) {
    Method readMethod = propertyDescriptor.getReadMethod();
    if (readMethod != null && readMethod.getDeclaringClass().getAnnotation(ManagedResource.class) != null)
    return super.getAttributeDescription(propertyDescriptor, beanKey);
    return propertyDescriptor.getDisplayName();
}

@Override
protected String getOperationDescription(Method method, String beanKey) {
    if (method.getDeclaringClass().getAnnotation(ManagedResource.class) != null)
    return super.getOperationDescription(method, beanKey);
    return method.getName(); 
}

@Override
protected void populateAttributeDescriptor(Descriptor desc, Method getter, Method setter, String beanKey) {
    Method  methodToUse = getter;
    if (methodToUse == null)
    methodToUse = setter;
    if (methodToUse != null) {
    if (methodToUse.getDeclaringClass().getAnnotation(ManagedResource.class) != null)
        super.populateAttributeDescriptor(desc, getter, setter, beanKey);
    else
        applyDefaultCurrencyTimeLimit(desc);
    }
    else
    applyDefaultCurrencyTimeLimit(desc);
}

@Override
protected void populateMBeanDescriptor(Descriptor descriptor, Object managedBean, String beanKey) {
    if (managedBean.getClass().getAnnotation(ManagedResource.class) != null)
    super.populateMBeanDescriptor(descriptor, managedBean, beanKey);
    else
    applyDefaultCurrencyTimeLimit(descriptor);
}

@Override
protected void populateOperationDescriptor(Descriptor desc, Method method, String beanKey) {
    if (method != null) {
    if (method.getClass().getAnnotation(ManagedResource.class) != null)
        super.populateOperationDescriptor(desc, method, beanKey);
    else
        applyDefaultCurrencyTimeLimit(desc);
    }
    else
    applyDefaultCurrencyTimeLimit(desc);
}
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM