Skip to content

Commit 0e02007

Browse files
jhoellerunknown
authored andcommitted
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
1 parent 8f8e517 commit 0e02007

File tree

8 files changed

+69
-18
lines changed

8 files changed

+69
-18
lines changed

spring-beans/src/main/java/org/springframework/beans/annotation/AnnotationBeanUtils.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2008 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
2525
import org.springframework.beans.BeanWrapper;
2626
import org.springframework.beans.PropertyAccessorFactory;
2727
import org.springframework.util.ReflectionUtils;
28+
import org.springframework.util.StringValueResolver;
2829

2930
/**
3031
* General utility methods for working with annotations in JavaBeans style.
@@ -38,16 +39,36 @@ public abstract class AnnotationBeanUtils {
3839
/**
3940
* Copy the properties of the supplied {@link Annotation} to the supplied target bean.
4041
* Any properties defined in <code>excludedProperties</code> will not be copied.
42+
* @param ann the annotation to copy from
43+
* @param bean the bean instance to copy to
44+
* @param excludedProperties the names of excluded properties, if any
4145
* @see org.springframework.beans.BeanWrapper
4246
*/
4347
public static void copyPropertiesToBean(Annotation ann, Object bean, String... excludedProperties) {
48+
copyPropertiesToBean(ann, bean, null, excludedProperties);
49+
}
50+
51+
/**
52+
* Copy the properties of the supplied {@link Annotation} to the supplied target bean.
53+
* Any properties defined in <code>excludedProperties</code> will not be copied.
54+
* <p>A specified value resolver may resolve placeholders in property values, for example.
55+
* @param ann the annotation to copy from
56+
* @param bean the bean instance to copy to
57+
* @param valueResolver a resolve to post-process String property values (may be <code>null</code>)
58+
* @param excludedProperties the names of excluded properties, if any
59+
* @see org.springframework.beans.BeanWrapper
60+
*/
61+
public static void copyPropertiesToBean(Annotation ann, Object bean, StringValueResolver valueResolver, String... excludedProperties) {
4462
Set<String> excluded = new HashSet<String>(Arrays.asList(excludedProperties));
4563
Method[] annotationProperties = ann.annotationType().getDeclaredMethods();
4664
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(bean);
4765
for (Method annotationProperty : annotationProperties) {
4866
String propertyName = annotationProperty.getName();
4967
if ((!excluded.contains(propertyName)) && bw.isWritableProperty(propertyName)) {
5068
Object value = ReflectionUtils.invokeMethod(annotationProperty, ann);
69+
if (valueResolver != null && value instanceof String) {
70+
value = valueResolver.resolveStringValue((String) value);
71+
}
5172
bw.setPropertyValue(propertyName, value);
5273
}
5374
}

spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,12 +16,11 @@
1616

1717
package org.springframework.jmx.export.annotation;
1818

19-
import java.beans.PropertyDescriptor;
2019
import java.lang.annotation.Annotation;
2120
import java.lang.reflect.Method;
2221

23-
import org.springframework.beans.BeanUtils;
2422
import org.springframework.beans.annotation.AnnotationBeanUtils;
23+
import org.springframework.context.EmbeddedValueResolverAware;
2524
import org.springframework.core.annotation.AnnotationUtils;
2625
import org.springframework.jmx.export.metadata.InvalidMetadataException;
2726
import org.springframework.jmx.export.metadata.JmxAttributeSource;
@@ -32,6 +31,7 @@
3231
import org.springframework.jmx.export.metadata.ManagedOperationParameter;
3332
import org.springframework.jmx.export.metadata.ManagedResource;
3433
import org.springframework.util.StringUtils;
34+
import org.springframework.util.StringValueResolver;
3535

3636
/**
3737
* Implementation of the <code>JmxAttributeSource</code> interface that
@@ -45,7 +45,15 @@
4545
* @see org.springframework.jmx.export.annotation.ManagedAttribute
4646
* @see org.springframework.jmx.export.annotation.ManagedOperation
4747
*/
48-
public class AnnotationJmxAttributeSource implements JmxAttributeSource {
48+
public class AnnotationJmxAttributeSource implements JmxAttributeSource, EmbeddedValueResolverAware {
49+
50+
private StringValueResolver embeddedValueResolver;
51+
52+
53+
public void setEmbeddedValueResolver(StringValueResolver resolver) {
54+
this.embeddedValueResolver = resolver;
55+
}
56+
4957

5058
public ManagedResource getManagedResource(Class<?> beanClass) throws InvalidMetadataException {
5159
org.springframework.jmx.export.annotation.ManagedResource ann =
@@ -54,9 +62,13 @@ public ManagedResource getManagedResource(Class<?> beanClass) throws InvalidMeta
5462
return null;
5563
}
5664
ManagedResource managedResource = new ManagedResource();
57-
AnnotationBeanUtils.copyPropertiesToBean(ann, managedResource);
65+
AnnotationBeanUtils.copyPropertiesToBean(ann, managedResource, this.embeddedValueResolver);
5866
if (!"".equals(ann.value()) && !StringUtils.hasLength(managedResource.getObjectName())) {
59-
managedResource.setObjectName(ann.value());
67+
String value = ann.value();
68+
if (this.embeddedValueResolver != null) {
69+
value = this.embeddedValueResolver.resolveStringValue(value);
70+
}
71+
managedResource.setObjectName(value);
6072
}
6173
return managedResource;
6274
}

spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationMBeanExporter.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2007 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,9 +16,11 @@
1616

1717
package org.springframework.jmx.export.annotation;
1818

19+
import org.springframework.context.EmbeddedValueResolverAware;
1920
import org.springframework.jmx.export.MBeanExporter;
2021
import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler;
2122
import org.springframework.jmx.export.naming.MetadataNamingStrategy;
23+
import org.springframework.util.StringValueResolver;
2224

2325
/**
2426
* Convenient subclass of Spring's standard {@link MBeanExporter},
@@ -32,7 +34,7 @@
3234
* @author Juergen Hoeller
3335
* @since 2.5
3436
*/
35-
public class AnnotationMBeanExporter extends MBeanExporter {
37+
public class AnnotationMBeanExporter extends MBeanExporter implements EmbeddedValueResolverAware {
3638

3739
private final AnnotationJmxAttributeSource annotationSource =
3840
new AnnotationJmxAttributeSource();
@@ -63,4 +65,8 @@ public void setDefaultDomain(String defaultDomain) {
6365
this.metadataNamingStrategy.setDefaultDomain(defaultDomain);
6466
}
6567

68+
public void setEmbeddedValueResolver(StringValueResolver resolver) {
69+
this.annotationSource.setEmbeddedValueResolver(resolver);
70+
}
71+
6672
}

spring-context/src/main/java/org/springframework/jmx/export/assembler/AbstractReflectiveMBeanInfoAssembler.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -164,6 +164,7 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
164164
*/
165165
protected static final String FIELD_METRIC_CATEGORY = "metricCategory";
166166

167+
167168
/**
168169
* Default value for the JMX field "currencyTimeLimit".
169170
*/
@@ -223,7 +224,7 @@ public void setUseStrictCasing(boolean useStrictCasing) {
223224
* Return whether strict casing for attributes is enabled.
224225
*/
225226
protected boolean isUseStrictCasing() {
226-
return useStrictCasing;
227+
return this.useStrictCasing;
227228
}
228229

229230
/**
@@ -250,7 +251,7 @@ public void setExposeClassDescriptor(boolean exposeClassDescriptor) {
250251
* Return whether to expose the JMX descriptor field "class" for managed operations.
251252
*/
252253
protected boolean isExposeClassDescriptor() {
253-
return exposeClassDescriptor;
254+
return this.exposeClassDescriptor;
254255
}
255256

256257

@@ -447,7 +448,6 @@ protected Class getClassForDescriptor(Object managedBean) {
447448
*/
448449
protected abstract boolean includeOperation(Method method, String beanKey);
449450

450-
451451
/**
452452
* Get the description for a particular attribute.
453453
* <p>The default implementation returns a description for the operation

spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationLazyInitMBeanTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public void testLazyNaming() throws Exception {
4747
}
4848

4949
public void testLazyAssembling() throws Exception {
50+
System.setProperty("domain", "bean");
5051
ConfigurableApplicationContext ctx =
5152
new ClassPathXmlApplicationContext("org/springframework/jmx/export/annotation/lazyAssembling.xml");
5253
try {
@@ -73,6 +74,7 @@ public void testLazyAssembling() throws Exception {
7374
assertEquals("Invalid name returned", "Juergen Hoeller", name);
7475
}
7576
finally {
77+
System.clearProperty("domain");
7678
ctx.close();
7779
}
7880
}

spring-context/src/test/java/org/springframework/jmx/export/annotation/EnableMBeanExportConfigurationTests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.junit.Test;
2323

24+
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
2425
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2526
import org.springframework.context.annotation.Bean;
2627
import org.springframework.context.annotation.ComponentScan;
@@ -62,6 +63,7 @@ public void testLazyNaming() throws Exception {
6263

6364
@Test
6465
public void testLazyAssembling() throws Exception {
66+
System.setProperty("domain", "bean");
6567
AnnotationConfigApplicationContext ctx =
6668
new AnnotationConfigApplicationContext(LazyAssemblingConfiguration.class);
6769
try {
@@ -88,6 +90,7 @@ public void testLazyAssembling() throws Exception {
8890
assertEquals("Invalid name returned", "Juergen Hoeller", name);
8991
}
9092
finally {
93+
System.clearProperty("domain");
9194
ctx.close();
9295
}
9396
}
@@ -130,6 +133,11 @@ public AnnotationTestBean testBean() {
130133
@EnableMBeanExport(server="server", registration=RegistrationPolicy.REPLACE_EXISTING)
131134
static class LazyAssemblingConfiguration {
132135

136+
@Bean
137+
public PropertyPlaceholderConfigurer ppc() {
138+
return new PropertyPlaceholderConfigurer();
139+
}
140+
133141
@Bean
134142
public MBeanServerFactoryBean server() throws Exception {
135143
return new MBeanServerFactoryBean();

spring-context/src/test/java/org/springframework/jmx/export/annotation/FactoryCreatedAnnotationTestBean.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2009 the original author or authors.
2+
* Copyright 2002-2012 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@
1919
/**
2020
* @author Juergen Hoeller
2121
*/
22-
@ManagedResource(objectName = "bean:name=testBean5")
22+
@ManagedResource("${domain}:name=testBean5")
2323
public class FactoryCreatedAnnotationTestBean extends AnnotationTestBean {
2424

2525
}

spring-context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77

88
<context:mbean-export server="server" registration="replaceExisting"/>
99

10-
<bean id="server" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
10+
<context:property-placeholder/>
1111

12-
<bean name="bean:name=testBean4" class="org.springframework.jmx.export.annotation.AnnotationTestBean" lazy-init="true">
12+
<bean id="server" class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
13+
14+
<bean name="testBean4" class="org.springframework.jmx.export.annotation.AnnotationTestBean" lazy-init="true">
1315
<property name="name" value="TEST"/>
1416
<property name="age" value="100"/>
1517
</bean>
1618

17-
<bean name="bean:name=testBean5" class="org.springframework.jmx.export.annotation.AnnotationTestBeanFactory"/>
19+
<bean name="testBean5" class="org.springframework.jmx.export.annotation.AnnotationTestBeanFactory"/>
1820

1921
<bean name="spring:mbean=true" class="org.springframework.jmx.export.TestDynamicMBean" lazy-init="true"/>
2022

0 commit comments

Comments
 (0)