ManagedResource annotation supports placeholders for String attributes
In particular, the specified object name may use a placeholder for its domain part now, allowing for several instances of the MBean to be registered against the same MBeanServer from different applications. Issue: SPR-8244
This commit is contained in:
parent
8f8e517c0d
commit
0e0200769d
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2008 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -25,6 +25,7 @@ import java.util.Set;
|
|||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* General utility methods for working with annotations in JavaBeans style.
|
||||
|
|
@ -38,9 +39,26 @@ public abstract class AnnotationBeanUtils {
|
|||
/**
|
||||
* Copy the properties of the supplied {@link Annotation} to the supplied target bean.
|
||||
* Any properties defined in <code>excludedProperties</code> will not be copied.
|
||||
* @param ann the annotation to copy from
|
||||
* @param bean the bean instance to copy to
|
||||
* @param excludedProperties the names of excluded properties, if any
|
||||
* @see org.springframework.beans.BeanWrapper
|
||||
*/
|
||||
public static void copyPropertiesToBean(Annotation ann, Object bean, String... excludedProperties) {
|
||||
copyPropertiesToBean(ann, bean, null, excludedProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the properties of the supplied {@link Annotation} to the supplied target bean.
|
||||
* Any properties defined in <code>excludedProperties</code> will not be copied.
|
||||
* <p>A specified value resolver may resolve placeholders in property values, for example.
|
||||
* @param ann the annotation to copy from
|
||||
* @param bean the bean instance to copy to
|
||||
* @param valueResolver a resolve to post-process String property values (may be <code>null</code>)
|
||||
* @param excludedProperties the names of excluded properties, if any
|
||||
* @see org.springframework.beans.BeanWrapper
|
||||
*/
|
||||
public static void copyPropertiesToBean(Annotation ann, Object bean, StringValueResolver valueResolver, String... excludedProperties) {
|
||||
Set<String> excluded = new HashSet<String>(Arrays.asList(excludedProperties));
|
||||
Method[] annotationProperties = ann.annotationType().getDeclaredMethods();
|
||||
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(bean);
|
||||
|
|
@ -48,6 +66,9 @@ public abstract class AnnotationBeanUtils {
|
|||
String propertyName = annotationProperty.getName();
|
||||
if ((!excluded.contains(propertyName)) && bw.isWritableProperty(propertyName)) {
|
||||
Object value = ReflectionUtils.invokeMethod(annotationProperty, ann);
|
||||
if (valueResolver != null && value instanceof String) {
|
||||
value = valueResolver.resolveStringValue((String) value);
|
||||
}
|
||||
bw.setPropertyValue(propertyName, value);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,12 +16,11 @@
|
|||
|
||||
package org.springframework.jmx.export.annotation;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.annotation.AnnotationBeanUtils;
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.jmx.export.metadata.InvalidMetadataException;
|
||||
import org.springframework.jmx.export.metadata.JmxAttributeSource;
|
||||
|
|
@ -32,6 +31,7 @@ import org.springframework.jmx.export.metadata.ManagedOperation;
|
|||
import org.springframework.jmx.export.metadata.ManagedOperationParameter;
|
||||
import org.springframework.jmx.export.metadata.ManagedResource;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* Implementation of the <code>JmxAttributeSource</code> interface that
|
||||
|
|
@ -45,7 +45,15 @@ import org.springframework.util.StringUtils;
|
|||
* @see org.springframework.jmx.export.annotation.ManagedAttribute
|
||||
* @see org.springframework.jmx.export.annotation.ManagedOperation
|
||||
*/
|
||||
public class AnnotationJmxAttributeSource implements JmxAttributeSource {
|
||||
public class AnnotationJmxAttributeSource implements JmxAttributeSource, EmbeddedValueResolverAware {
|
||||
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.embeddedValueResolver = resolver;
|
||||
}
|
||||
|
||||
|
||||
public ManagedResource getManagedResource(Class<?> beanClass) throws InvalidMetadataException {
|
||||
org.springframework.jmx.export.annotation.ManagedResource ann =
|
||||
|
|
@ -54,9 +62,13 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource {
|
|||
return null;
|
||||
}
|
||||
ManagedResource managedResource = new ManagedResource();
|
||||
AnnotationBeanUtils.copyPropertiesToBean(ann, managedResource);
|
||||
AnnotationBeanUtils.copyPropertiesToBean(ann, managedResource, this.embeddedValueResolver);
|
||||
if (!"".equals(ann.value()) && !StringUtils.hasLength(managedResource.getObjectName())) {
|
||||
managedResource.setObjectName(ann.value());
|
||||
String value = ann.value();
|
||||
if (this.embeddedValueResolver != null) {
|
||||
value = this.embeddedValueResolver.resolveStringValue(value);
|
||||
}
|
||||
managedResource.setObjectName(value);
|
||||
}
|
||||
return managedResource;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
package org.springframework.jmx.export.annotation;
|
||||
|
||||
import org.springframework.context.EmbeddedValueResolverAware;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler;
|
||||
import org.springframework.jmx.export.naming.MetadataNamingStrategy;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
|
||||
/**
|
||||
* Convenient subclass of Spring's standard {@link MBeanExporter},
|
||||
|
|
@ -32,7 +34,7 @@ import org.springframework.jmx.export.naming.MetadataNamingStrategy;
|
|||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
*/
|
||||
public class AnnotationMBeanExporter extends MBeanExporter {
|
||||
public class AnnotationMBeanExporter extends MBeanExporter implements EmbeddedValueResolverAware {
|
||||
|
||||
private final AnnotationJmxAttributeSource annotationSource =
|
||||
new AnnotationJmxAttributeSource();
|
||||
|
|
@ -63,4 +65,8 @@ public class AnnotationMBeanExporter extends MBeanExporter {
|
|||
this.metadataNamingStrategy.setDefaultDomain(defaultDomain);
|
||||
}
|
||||
|
||||
public void setEmbeddedValueResolver(StringValueResolver resolver) {
|
||||
this.annotationSource.setEmbeddedValueResolver(resolver);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -164,6 +164,7 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
|
|||
*/
|
||||
protected static final String FIELD_METRIC_CATEGORY = "metricCategory";
|
||||
|
||||
|
||||
/**
|
||||
* Default value for the JMX field "currencyTimeLimit".
|
||||
*/
|
||||
|
|
@ -223,7 +224,7 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
|
|||
* Return whether strict casing for attributes is enabled.
|
||||
*/
|
||||
protected boolean isUseStrictCasing() {
|
||||
return useStrictCasing;
|
||||
return this.useStrictCasing;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -250,7 +251,7 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
|
|||
* Return whether to expose the JMX descriptor field "class" for managed operations.
|
||||
*/
|
||||
protected boolean isExposeClassDescriptor() {
|
||||
return exposeClassDescriptor;
|
||||
return this.exposeClassDescriptor;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -447,7 +448,6 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
|
|||
*/
|
||||
protected abstract boolean includeOperation(Method method, String beanKey);
|
||||
|
||||
|
||||
/**
|
||||
* Get the description for a particular attribute.
|
||||
* <p>The default implementation returns a description for the operation
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public class AnnotationLazyInitMBeanTests extends TestCase {
|
|||
}
|
||||
|
||||
public void testLazyAssembling() throws Exception {
|
||||
System.setProperty("domain", "bean");
|
||||
ConfigurableApplicationContext ctx =
|
||||
new ClassPathXmlApplicationContext("org/springframework/jmx/export/annotation/lazyAssembling.xml");
|
||||
try {
|
||||
|
|
@ -73,6 +74,7 @@ public class AnnotationLazyInitMBeanTests extends TestCase {
|
|||
assertEquals("Invalid name returned", "Juergen Hoeller", name);
|
||||
}
|
||||
finally {
|
||||
System.clearProperty("domain");
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import javax.management.ObjectName;
|
|||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
|
@ -62,6 +63,7 @@ public class EnableMBeanExportConfigurationTests {
|
|||
|
||||
@Test
|
||||
public void testLazyAssembling() throws Exception {
|
||||
System.setProperty("domain", "bean");
|
||||
AnnotationConfigApplicationContext ctx =
|
||||
new AnnotationConfigApplicationContext(LazyAssemblingConfiguration.class);
|
||||
try {
|
||||
|
|
@ -88,6 +90,7 @@ public class EnableMBeanExportConfigurationTests {
|
|||
assertEquals("Invalid name returned", "Juergen Hoeller", name);
|
||||
}
|
||||
finally {
|
||||
System.clearProperty("domain");
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -130,6 +133,11 @@ public class EnableMBeanExportConfigurationTests {
|
|||
@EnableMBeanExport(server="server", registration=RegistrationPolicy.REPLACE_EXISTING)
|
||||
static class LazyAssemblingConfiguration {
|
||||
|
||||
@Bean
|
||||
public PropertyPlaceholderConfigurer ppc() {
|
||||
return new PropertyPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MBeanServerFactoryBean server() throws Exception {
|
||||
return new MBeanServerFactoryBean();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -19,7 +19,7 @@ package org.springframework.jmx.export.annotation;
|
|||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
@ManagedResource(objectName = "bean:name=testBean5")
|
||||
@ManagedResource("${domain}:name=testBean5")
|
||||
public class FactoryCreatedAnnotationTestBean extends AnnotationTestBean {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,16 @@
|
|||
|
||||
<context:mbean-export server="server" registration="replaceExisting"/>
|
||||
|
||||
<bean id="server" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
|
||||
<context:property-placeholder/>
|
||||
|
||||
<bean name="bean:name=testBean4" class="org.springframework.jmx.export.annotation.AnnotationTestBean" lazy-init="true">
|
||||
<bean id="server" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
|
||||
|
||||
<bean name="testBean4" class="org.springframework.jmx.export.annotation.AnnotationTestBean" lazy-init="true">
|
||||
<property name="name" value="TEST"/>
|
||||
<property name="age" value="100"/>
|
||||
</bean>
|
||||
|
||||
<bean name="bean:name=testBean5" class="org.springframework.jmx.export.annotation.AnnotationTestBeanFactory"/>
|
||||
<bean name="testBean5" class="org.springframework.jmx.export.annotation.AnnotationTestBeanFactory"/>
|
||||
|
||||
<bean name="spring:mbean=true" class="org.springframework.jmx.export.TestDynamicMBean" lazy-init="true"/>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue