Skip to content

Commit c977101

Browse files
committed
Introduced @description annotation for populating BeanDefinition.getDescription()
Issue: SPR-10583
1 parent cf2e1ff commit c977101

14 files changed

+137
-164
lines changed

spring-context/src/main/java/org/springframework/context/annotation/AdviceModeImportSelector.java

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 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.
@@ -23,23 +23,20 @@
2323
import org.springframework.core.type.AnnotationMetadata;
2424
import org.springframework.util.Assert;
2525

26-
import static org.springframework.context.annotation.MetadataUtils.*;
27-
28-
/**
26+
/**
2927
* Convenient base class for {@link ImportSelector} implementations that select imports
3028
* based on an {@link AdviceMode} value from an annotation (such as the {@code @Enable*}
3129
* annotations).
3230
*
33-
* @param <A> Annotation containing {@linkplain #getAdviceModeAttributeName() AdviceMode
34-
* attribute}
35-
*
31+
* @param <A> Annotation containing {@linkplain #getAdviceModeAttributeName() AdviceMode attribute}
3632
* @author Chris Beams
3733
* @since 3.1
3834
*/
3935
public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {
4036

4137
public static final String DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME = "mode";
4238

39+
4340
/**
4441
* The name of the {@link AdviceMode} attribute for the annotation specified by the
4542
* generic type {@code A}. The default is {@value #DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME},
@@ -50,48 +47,38 @@ protected String getAdviceModeAttributeName() {
5047
}
5148

5249
/**
53-
* {@inheritDoc}
54-
*
55-
* <p>This implementation resolves the type of annotation from generic metadata and
50+
* This implementation resolves the type of annotation from generic metadata and
5651
* validates that (a) the annotation is in fact present on the importing
5752
* {@code @Configuration} class and (b) that the given annotation has an
5853
* {@linkplain #getAdviceModeAttributeName() advice mode attribute} of type
5954
* {@link AdviceMode}.
60-
*
6155
* <p>The {@link #selectImports(AdviceMode)} method is then invoked, allowing the
6256
* concrete implementation to choose imports in a safe and convenient fashion.
63-
*
6457
* @throws IllegalArgumentException if expected annotation {@code A} is not present
6558
* on the importing {@code @Configuration} class or if {@link #selectImports(AdviceMode)}
6659
* returns {@code null}
6760
*/
6861
@Override
6962
public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
7063
Class<?> annoType = GenericTypeResolver.resolveTypeArgument(this.getClass(), AdviceModeImportSelector.class);
71-
72-
AnnotationAttributes attributes = attributesFor(importingClassMetadata, annoType);
64+
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
7365
Assert.notNull(attributes, String.format(
7466
"@%s is not present on importing class '%s' as expected",
7567
annoType.getSimpleName(), importingClassMetadata.getClassName()));
7668

7769
AdviceMode adviceMode = attributes.getEnum(this.getAdviceModeAttributeName());
78-
7970
String[] imports = selectImports(adviceMode);
8071
Assert.notNull(imports, String.format("Unknown AdviceMode: '%s'", adviceMode));
81-
8272
return imports;
8373
}
8474

8575
/**
8676
* Determine which classes should be imported based on the given {@code AdviceMode}.
87-
*
8877
* <p>Returning {@code null} from this method indicates that the {@code AdviceMode} could
8978
* not be handled or was unknown and that an {@code IllegalArgumentException} should
9079
* be thrown.
91-
*
9280
* @param adviceMode the value of the {@linkplain #getAdviceModeAttributeName()
9381
* advice mode attribute} for the annotation specified via generics.
94-
*
9582
* @return array containing classes to import; empty array if none, {@code null} if
9683
* the given {@code AdviceMode} is unknown.
9784
*/

spring-context/src/main/java/org/springframework/context/annotation/AnnotationBeanNameGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotat
8787
Set<String> types = amd.getAnnotationTypes();
8888
String beanName = null;
8989
for (String type : types) {
90-
AnnotationAttributes attributes = MetadataUtils.attributesFor(amd, type);
90+
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
9191
if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
9292
String value = (String) attributes.get("value");
9393
if (StringUtils.hasLength(value)) {

spring-context/src/main/java/org/springframework/context/annotation/AnnotationConfigUtils.java

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 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.
@@ -27,11 +27,10 @@
2727
import org.springframework.beans.factory.support.AbstractBeanDefinition;
2828
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
2929
import org.springframework.beans.factory.support.RootBeanDefinition;
30-
import org.springframework.core.type.AnnotationMetadata;
30+
import org.springframework.core.annotation.AnnotationAttributes;
31+
import org.springframework.core.type.AnnotatedTypeMetadata;
3132
import org.springframework.util.ClassUtils;
3233

33-
import static org.springframework.context.annotation.MetadataUtils.*;
34-
3534
/**
3635
* Utility class that allows for convenient registration of common
3736
* {@link org.springframework.beans.factory.config.BeanPostProcessor} and
@@ -231,20 +230,31 @@ private static BeanDefinitionHolder registerPostProcessor(
231230
}
232231

233232
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
234-
AnnotationMetadata metadata = abd.getMetadata();
235-
if (metadata.isAnnotated(Primary.class.getName())) {
236-
abd.setPrimary(true);
237-
}
233+
processCommonDefinitionAnnotations(abd, abd.getMetadata());
234+
}
235+
236+
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
238237
if (metadata.isAnnotated(Lazy.class.getName())) {
239238
abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
240239
}
240+
else if (abd.getMetadata().isAnnotated(Lazy.class.getName())) {
241+
abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
242+
}
243+
244+
if (metadata.isAnnotated(Primary.class.getName())) {
245+
abd.setPrimary(true);
246+
}
241247
if (metadata.isAnnotated(DependsOn.class.getName())) {
242248
abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
243249
}
250+
244251
if (abd instanceof AbstractBeanDefinition) {
252+
AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
245253
if (metadata.isAnnotated(Role.class.getName())) {
246-
Integer role = attributesFor(metadata, Role.class).getNumber("value");
247-
((AbstractBeanDefinition)abd).setRole(role);
254+
absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
255+
}
256+
if (metadata.isAnnotated(Description.class.getName())) {
257+
absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
248258
}
249259
}
250260
}
@@ -260,5 +270,12 @@ static BeanDefinitionHolder applyScopedProxyMode(
260270
return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
261271
}
262272

273+
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annoClass) {
274+
return attributesFor(metadata, annoClass.getName());
275+
}
276+
277+
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annoClassName) {
278+
return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annoClassName, false));
279+
}
263280

264281
}

spring-context/src/main/java/org/springframework/context/annotation/AnnotationScopeMetadataResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
7777
ScopeMetadata metadata = new ScopeMetadata();
7878
if (definition instanceof AnnotatedBeanDefinition) {
7979
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
80-
AnnotationAttributes attributes = MetadataUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
80+
AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
8181
if (attributes != null) {
8282
metadata.setScopeName(attributes.getString("value"));
8383
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");

spring-context/src/main/java/org/springframework/context/annotation/AspectJAutoProxyRegistrar.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 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.
@@ -21,16 +21,14 @@
2121
import org.springframework.core.annotation.AnnotationAttributes;
2222
import org.springframework.core.type.AnnotationMetadata;
2323

24-
import static org.springframework.context.annotation.MetadataUtils.*;
25-
2624
/**
2725
* Registers an {@link org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
2826
* AnnotationAwareAspectJAutoProxyCreator} against the current {@link BeanDefinitionRegistry}
2927
* as appropriate based on a given @{@link EnableAspectJAutoProxy} annotation.
3028
*
3129
* @author Chris Beams
32-
* @see EnableAspectJAutoProxy
3330
* @since 3.1
31+
* @see EnableAspectJAutoProxy
3432
*/
3533
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
3634

@@ -46,7 +44,7 @@ public void registerBeanDefinitions(
4644
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
4745

4846
AnnotationAttributes enableAJAutoProxy =
49-
attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
47+
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
5048
if (enableAJAutoProxy.getBoolean("proxyTargetClass")) {
5149
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
5250
}

spring-context/src/main/java/org/springframework/context/annotation/AutoProxyRegistrar.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2013 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,8 +16,6 @@
1616

1717
package org.springframework.context.annotation;
1818

19-
import static org.springframework.context.annotation.MetadataUtils.attributesFor;
20-
2119
import java.util.Set;
2220

2321
import org.apache.commons.logging.Log;
@@ -61,7 +59,7 @@ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, B
6159
boolean candidateFound = false;
6260
Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
6361
for (String annoType : annoTypes) {
64-
AnnotationAttributes candidate = attributesFor(importingClassMetadata, annoType);
62+
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
6563
Object mode = candidate.get("mode");
6664
Object proxyTargetClass = candidate.get("proxyTargetClass");
6765
if (mode != null && proxyTargetClass != null

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@
5353
import org.springframework.core.type.classreading.MetadataReaderFactory;
5454
import org.springframework.util.StringUtils;
5555

56-
import static org.springframework.context.annotation.MetadataUtils.*;
57-
5856
/**
5957
* Reads a given fully-populated set of ConfigurationClass instances, registering bean
6058
* definitions with the given {@link BeanDefinitionRegistry} based on its contents.
@@ -178,14 +176,13 @@ private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationCl
178176
* with the BeanDefinitionRegistry based on its contents.
179177
*/
180178
private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
181-
if (conditionEvaluator.shouldSkip(beanMethod.getMetadata(),
182-
ConfigurationPhase.REGISTER_BEAN)) {
179+
if (this.conditionEvaluator.shouldSkip(beanMethod.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
183180
return;
184181
}
185182
ConfigurationClass configClass = beanMethod.getConfigurationClass();
186183
MethodMetadata metadata = beanMethod.getMetadata();
187184

188-
RootBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass);
185+
ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass);
189186
beanDef.setResource(configClass.getResource());
190187
beanDef.setSource(this.sourceExtractor.extractSource(metadata, configClass.getResource()));
191188
if (metadata.isStatic()) {
@@ -201,14 +198,8 @@ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
201198
beanDef.setAutowireMode(RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
202199
beanDef.setAttribute(RequiredAnnotationBeanPostProcessor.SKIP_REQUIRED_CHECK_ATTRIBUTE, Boolean.TRUE);
203200

204-
// consider role
205-
AnnotationAttributes role = attributesFor(metadata, Role.class);
206-
if (role != null) {
207-
beanDef.setRole(role.<Integer>getNumber("value"));
208-
}
209-
210201
// consider name and any aliases
211-
AnnotationAttributes bean = attributesFor(metadata, Bean.class);
202+
AnnotationAttributes bean = AnnotationConfigUtils.attributesFor(metadata, Bean.class);
212203
List<String> names = new ArrayList<String>(Arrays.asList(bean.getStringArray("name")));
213204
String beanName = (names.size() > 0 ? names.remove(0) : beanMethod.getMetadata().getMethodName());
214205
for (String alias : names) {
@@ -230,27 +221,7 @@ private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
230221
}
231222
}
232223

233-
if (metadata.isAnnotated(Primary.class.getName())) {
234-
beanDef.setPrimary(true);
235-
}
236-
237-
// is this bean to be instantiated lazily?
238-
if (metadata.isAnnotated(Lazy.class.getName())) {
239-
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
240-
beanDef.setLazyInit(lazy.getBoolean("value"));
241-
}
242-
else if (configClass.getMetadata().isAnnotated(Lazy.class.getName())){
243-
AnnotationAttributes lazy = attributesFor(configClass.getMetadata(), Lazy.class);
244-
beanDef.setLazyInit(lazy.getBoolean("value"));
245-
}
246-
247-
if (metadata.isAnnotated(DependsOn.class.getName())) {
248-
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
249-
String[] otherBeans = dependsOn.getStringArray("value");
250-
if (otherBeans.length > 0) {
251-
beanDef.setDependsOn(otherBeans);
252-
}
253-
}
224+
AnnotationConfigUtils.processCommonDefinitionAnnotations(beanDef, metadata);
254225

255226
Autowire autowire = bean.getEnum("autowire");
256227
if (autowire.isAutowire()) {
@@ -269,7 +240,7 @@ else if (configClass.getMetadata().isAnnotated(Lazy.class.getName())){
269240

270241
// consider scoping
271242
ScopedProxyMode proxyMode = ScopedProxyMode.NO;
272-
AnnotationAttributes scope = attributesFor(metadata, Scope.class);
243+
AnnotationAttributes scope = AnnotationConfigUtils.attributesFor(metadata, Scope.class);
273244
if (scope != null) {
274245
beanDef.setScope(scope.getString("value"));
275246
proxyMode = scope.getEnum("proxyMode");

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@
6666
import org.springframework.core.type.filter.AssignableTypeFilter;
6767
import org.springframework.util.StringUtils;
6868

69-
import static org.springframework.context.annotation.MetadataUtils.*;
70-
7169
/**
7270
* Parses a {@link Configuration} class definition, populating a collection of
7371
* {@link ConfigurationClass} objects (parsing a single Configuration class may result in
@@ -223,13 +221,13 @@ protected final SourceClass doProcessConfigurationClass(ConfigurationClass confi
223221
processMemberClasses(configClass, sourceClass);
224222

225223
// process any @PropertySource annotations
226-
AnnotationAttributes propertySource = attributesFor(sourceClass.getMetadata(), org.springframework.context.annotation.PropertySource.class);
224+
AnnotationAttributes propertySource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), org.springframework.context.annotation.PropertySource.class);
227225
if (propertySource != null) {
228226
processPropertySource(propertySource);
229227
}
230228

231229
// process any @ComponentScan annotations
232-
AnnotationAttributes componentScan = attributesFor(sourceClass.getMetadata(), ComponentScan.class);
230+
AnnotationAttributes componentScan = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ComponentScan.class);
233231
if (componentScan != null) {
234232
// the config class is annotated with @ComponentScan -> perform the scan immediately
235233
if (!conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
@@ -250,7 +248,7 @@ protected final SourceClass doProcessConfigurationClass(ConfigurationClass confi
250248

251249
// process any @ImportResource annotations
252250
if (sourceClass.getMetadata().isAnnotated(ImportResource.class.getName())) {
253-
AnnotationAttributes importResource = attributesFor(sourceClass.getMetadata(), ImportResource.class);
251+
AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
254252
String[] resources = importResource.getStringArray("value");
255253
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
256254
for (String resource : resources) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2002-2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.context.annotation;
18+
19+
import java.lang.annotation.Documented;
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.RetentionPolicy;
23+
import java.lang.annotation.Target;
24+
25+
/**
26+
* Adds a textual description to bean definitions derived from
27+
* {@link org.springframework.stereotype.Component} or {@link Bean}.
28+
*
29+
* @author Juergen Hoeller
30+
* @since 4.0
31+
* @see org.springframework.beans.factory.config.BeanDefinition#getDescription()
32+
*/
33+
@Target({ElementType.METHOD, ElementType.TYPE})
34+
@Retention(RetentionPolicy.RUNTIME)
35+
@Documented
36+
public @interface Description {
37+
38+
/**
39+
* The textual description to associate with the bean definition.
40+
*/
41+
String value();
42+
43+
}

0 commit comments

Comments
 (0)