Support annotation attribute aliases and overrides via @AliasFor
This commit introduces first-class support for aliases for annotation
attributes. Specifically, this commit introduces a new @AliasFor
annotation that can be used to declare a pair of aliased attributes
within a single annotation or an alias from an attribute in a custom
composed annotation to an attribute in a meta-annotation.
To support @AliasFor within annotation instances, AnnotationUtils has
been overhauled to "synthesize" any annotations returned by "get" and
"find" searches. A SynthesizedAnnotation is an annotation that is
wrapped in a JDK dynamic proxy which provides run-time support for
@AliasFor semantics. SynthesizedAnnotationInvocationHandler is the
actual handler behind the proxy.
In addition, the contract for @AliasFor is fully validated, and an
AnnotationConfigurationException is thrown in case invalid
configuration is detected.
For example, @ContextConfiguration from the spring-test module is now
declared as follows:
public @interface ContextConfiguration {
@AliasFor(attribute = "locations")
String[] value() default {};
@AliasFor(attribute = "value")
String[] locations() default {};
// ...
}
The following annotations and their related support classes have been
modified to use @AliasFor.
- @ManagedResource
- @ContextConfiguration
- @ActiveProfiles
- @TestExecutionListeners
- @TestPropertySource
- @Sql
- @ControllerAdvice
- @RequestMapping
Similarly, support for AnnotationAttributes has been reworked to
support @AliasFor as well. This allows for fine-grained control over
exactly which attributes are overridden within an annotation hierarchy.
In fact, it is now possible to declare an alias for the 'value'
attribute of a meta-annotation.
For example, given the revised declaration of @ContextConfiguration
above, one can now develop a composed annotation with a custom
attribute override as follows.
@ContextConfiguration
public @interface MyTestConfig {
@AliasFor(
annotation = ContextConfiguration.class,
attribute = "locations"
)
String[] xmlFiles();
// ...
}
Consequently, the following are functionally equivalent.
- @MyTestConfig(xmlFiles = "test.xml")
- @ContextConfiguration("test.xml")
- @ContextConfiguration(locations = "test.xml").
Issue: SPR-11512, SPR-11513
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -32,7 +32,6 @@ import org.springframework.jmx.export.metadata.ManagedNotification;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -66,7 +65,6 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFac
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ManagedResource getManagedResource(Class<?> beanClass) throws InvalidMetadataException {
|
||||
org.springframework.jmx.export.annotation.ManagedResource ann =
|
||||
@@ -76,13 +74,6 @@ public class AnnotationJmxAttributeSource implements JmxAttributeSource, BeanFac
|
||||
}
|
||||
ManagedResource managedResource = new ManagedResource();
|
||||
AnnotationBeanUtils.copyPropertiesToBean(ann, managedResource, this.embeddedValueResolver);
|
||||
if (!"".equals(ann.value()) && !StringUtils.hasLength(managedResource.getObjectName())) {
|
||||
String value = ann.value();
|
||||
if (this.embeddedValueResolver != null) {
|
||||
value = this.embeddedValueResolver.resolveStringValue(value);
|
||||
}
|
||||
managedResource.setObjectName(value);
|
||||
}
|
||||
return managedResource;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2015 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.
|
||||
@@ -23,6 +23,8 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* JDK 1.5+ class-level annotation that indicates to register instances of a
|
||||
* class with a JMX server, corresponding to the ManagedResource attribute.
|
||||
@@ -34,6 +36,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 1.2
|
||||
* @see org.springframework.jmx.export.metadata.ManagedResource
|
||||
*/
|
||||
@@ -44,11 +47,12 @@ import java.lang.annotation.Target;
|
||||
public @interface ManagedResource {
|
||||
|
||||
/**
|
||||
* The annotation value is equivalent to the {@code objectName}
|
||||
* attribute, for simple default usage.
|
||||
* Alias for the {@link #objectName} attribute, for simple default usage.
|
||||
*/
|
||||
@AliasFor(attribute = "objectName")
|
||||
String value() default "";
|
||||
|
||||
@AliasFor(attribute = "value")
|
||||
String objectName() default "";
|
||||
|
||||
String description() default "";
|
||||
|
||||
Reference in New Issue
Block a user