diff --git a/spring-beans/src/main/java/org/springframework/beans/annotation/AnnotationBeanUtils.java b/spring-beans/src/main/java/org/springframework/beans/annotation/AnnotationBeanUtils.java index ac337034c9..db3c74965b 100644 --- a/spring-beans/src/main/java/org/springframework/beans/annotation/AnnotationBeanUtils.java +++ b/spring-beans/src/main/java/org/springframework/beans/annotation/AnnotationBeanUtils.java @@ -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 excludedProperties 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 excludedProperties will not be copied. + *

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 null) + * @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 excluded = new HashSet(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); } } diff --git a/spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java b/spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java index 5b5675f781..8ac3f93501 100644 --- a/spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java +++ b/spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationJmxAttributeSource.java @@ -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 JmxAttributeSource 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; } diff --git a/spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationMBeanExporter.java b/spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationMBeanExporter.java index a0aaf70c5d..681bd15724 100644 --- a/spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationMBeanExporter.java +++ b/spring-context/src/main/java/org/springframework/jmx/export/annotation/AnnotationMBeanExporter.java @@ -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); + } + } diff --git a/spring-context/src/main/java/org/springframework/jmx/export/assembler/AbstractReflectiveMBeanInfoAssembler.java b/spring-context/src/main/java/org/springframework/jmx/export/assembler/AbstractReflectiveMBeanInfoAssembler.java index 70b52f96a6..a701a5d0f6 100644 --- a/spring-context/src/main/java/org/springframework/jmx/export/assembler/AbstractReflectiveMBeanInfoAssembler.java +++ b/spring-context/src/main/java/org/springframework/jmx/export/assembler/AbstractReflectiveMBeanInfoAssembler.java @@ -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. *

The default implementation returns a description for the operation diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationLazyInitMBeanTests.java b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationLazyInitMBeanTests.java index 3e323e7ca6..0083c77aa1 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationLazyInitMBeanTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/AnnotationLazyInitMBeanTests.java @@ -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(); } } diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/EnableMBeanExportConfigurationTests.java b/spring-context/src/test/java/org/springframework/jmx/export/annotation/EnableMBeanExportConfigurationTests.java index 3dd6cfe08c..88af043b16 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/EnableMBeanExportConfigurationTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/EnableMBeanExportConfigurationTests.java @@ -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(); diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/FactoryCreatedAnnotationTestBean.java b/spring-context/src/test/java/org/springframework/jmx/export/annotation/FactoryCreatedAnnotationTestBean.java index 2741a8b97c..f4f83ebb97 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/FactoryCreatedAnnotationTestBean.java +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/FactoryCreatedAnnotationTestBean.java @@ -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 { } diff --git a/spring-context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml b/spring-context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml index f06f02b354..c11ca5fc82 100644 --- a/spring-context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml +++ b/spring-context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml @@ -7,14 +7,16 @@ - + - + + + - +