diff --git a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationScopeMetadataResolver.java b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationScopeMetadataResolver.java index 5d4ce9c9522..fe56aa2f458 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/AnnotationScopeMetadataResolver.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/AnnotationScopeMetadataResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 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. @@ -25,13 +25,14 @@ import org.springframework.util.Assert; /** * A {@link ScopeMetadataResolver} implementation that by default checks for - * the presence of Spring's {@link Scope} annotation on the bean class. + * the presence of Spring's {@link Scope @Scope} annotation on the bean class. * - *
The exact type of annotation that is checked for is configurable via the - * {@link #setScopeAnnotationType(Class)} property. + *
The exact type of annotation that is checked for is configurable via + * {@link #setScopeAnnotationType(Class)}. * * @author Mark Fisher * @author Juergen Hoeller + * @author Sam Brannen * @since 2.5 * @see org.springframework.context.annotation.Scope */ @@ -43,27 +44,27 @@ public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver { /** - * Create a new instance of the {@code AnnotationScopeMetadataResolver} class. + * Construct a new {@code AnnotationScopeMetadataResolver}. * @see #AnnotationScopeMetadataResolver(ScopedProxyMode) * @see ScopedProxyMode#NO */ public AnnotationScopeMetadataResolver() { - this.defaultProxyMode = ScopedProxyMode.NO; + this(ScopedProxyMode.NO); } /** - * Create a new instance of the {@code AnnotationScopeMetadataResolver} class. - * @param defaultProxyMode the desired scoped-proxy mode + * Construct a new {@code AnnotationScopeMetadataResolver} using the + * supplied default {@link ScopedProxyMode}. + * @param defaultProxyMode the default scoped-proxy mode */ public AnnotationScopeMetadataResolver(ScopedProxyMode defaultProxyMode) { Assert.notNull(defaultProxyMode, "'defaultProxyMode' must not be null"); this.defaultProxyMode = defaultProxyMode; } - /** * Set the type of annotation that is checked for by this - * {@link AnnotationScopeMetadataResolver}. + * {@code AnnotationScopeMetadataResolver}. * @param scopeAnnotationType the target annotation type */ public void setScopeAnnotationType(Class extends Annotation> scopeAnnotationType) { @@ -71,7 +72,6 @@ public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver { this.scopeAnnotationType = scopeAnnotationType; } - @Override public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) { ScopeMetadata metadata = new ScopeMetadata(); @@ -79,9 +79,9 @@ public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver { AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition; AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(annDef.getMetadata(), this.scopeAnnotationType); if (attributes != null) { - metadata.setScopeName(attributes.getString("value")); + metadata.setScopeName(attributes.getAliasedString("value", this.scopeAnnotationType, definition.getSource())); ScopedProxyMode proxyMode = attributes.getEnum("proxyMode"); - if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) { + if ((proxyMode == null) || (proxyMode == ScopedProxyMode.DEFAULT)) { proxyMode = this.defaultProxyMode; } metadata.setScopedProxyMode(proxyMode); diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index 033d27e58eb..7af760f41c4 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -65,6 +65,7 @@ import org.springframework.util.StringUtils; * @author Chris Beams * @author Juergen Hoeller * @author Phillip Webb + * @author Sam Brannen * @since 3.0 * @see ConfigurationClassParser */ @@ -242,10 +243,12 @@ class ConfigurationClassBeanDefinitionReader { // Consider scoping ScopedProxyMode proxyMode = ScopedProxyMode.NO; - AnnotationAttributes scope = AnnotationConfigUtils.attributesFor(metadata, Scope.class); - if (scope != null) { - beanDef.setScope(scope.getString("value")); - proxyMode = scope.getEnum("proxyMode"); + // TODO Determine why type is hard coded to org.springframework.context.annotation.Scope, + // since AnnotationScopeMetadataResolver supports a custom scope annotation type. + AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(metadata, Scope.class); + if (attributes != null) { + beanDef.setScope(attributes.getAliasedString("value", Scope.class, configClass.getResource())); + proxyMode = attributes.getEnum("proxyMode"); if (proxyMode == ScopedProxyMode.DEFAULT) { proxyMode = ScopedProxyMode.NO; } diff --git a/spring-context/src/main/java/org/springframework/context/annotation/Scope.java b/spring-context/src/main/java/org/springframework/context/annotation/Scope.java index c9c45f83d9b..8df50327ade 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/Scope.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/Scope.java @@ -23,6 +23,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.core.annotation.AliasFor; /** * When used as a type-level annotation in conjunction with @@ -57,14 +58,25 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory; public @interface Scope { /** - * Specifies the scope to use for the annotated component/bean. - *
Defaults to {@link ConfigurableBeanFactory#SCOPE_SINGLETON SCOPE_SINGLETON}. - * @see ConfigurableBeanFactory#SCOPE_SINGLETON + * Alias for {@link #name}. + * @see #name + */ + @AliasFor(attribute = "name") + String value() default ""; + + /** + * Specifies the name of the scope to use for the annotated component/bean. + *
Defaults to an empty string ({@code ""}) which implies
+ * {@link ConfigurableBeanFactory#SCOPE_SINGLETON SCOPE_SINGLETON}.
+ * @since 4.2
* @see ConfigurableBeanFactory#SCOPE_PROTOTYPE
+ * @see ConfigurableBeanFactory#SCOPE_SINGLETON
* @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST
* @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION
+ * @see #value
*/
- String value() default ConfigurableBeanFactory.SCOPE_SINGLETON;
+ @AliasFor(attribute = "value")
+ String name() default "";
/**
* Specifies whether a component should be configured as a scoped proxy
diff --git a/spring-context/src/test/java/org/springframework/context/annotation/AnnotationScopeMetadataResolverTests.java b/spring-context/src/test/java/org/springframework/context/annotation/AnnotationScopeMetadataResolverTests.java
index 5f0de59982c..6423156c81f 100644
--- a/spring-context/src/test/java/org/springframework/context/annotation/AnnotationScopeMetadataResolverTests.java
+++ b/spring-context/src/test/java/org/springframework/context/annotation/AnnotationScopeMetadataResolverTests.java
@@ -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.
@@ -17,12 +17,9 @@
package org.springframework.context.annotation;
import java.io.IOException;
-import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
@@ -33,137 +30,130 @@ import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.classreading.SimpleMetadataReaderFactory;
import static org.junit.Assert.*;
+import static org.springframework.context.annotation.ScopedProxyMode.*;
/**
+ * Unit tests for {@link AnnotationScopeMetadataResolver}.
+ *
* @author Rick Evans
* @author Chris Beams
* @author Juergen Hoeller
+ * @author Sam Brannen
*/
-public final class AnnotationScopeMetadataResolverTests {
-
- private AnnotationScopeMetadataResolver scopeMetadataResolver;
-
-
- @Before
- public void setUp() throws Exception {
- this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
- }
+public class AnnotationScopeMetadataResolverTests {
+ private AnnotationScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
@Test
- public void testThatResolveScopeMetadataDoesNotApplyScopedProxyModeToASingleton() {
+ public void resolveScopeMetadataShouldNotApplyScopedProxyModeToSingleton() {
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithSingletonScope.class);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
assertEquals(BeanDefinition.SCOPE_SINGLETON, scopeMetadata.getScopeName());
- assertEquals(ScopedProxyMode.NO, scopeMetadata.getScopedProxyMode());
+ assertEquals(NO, scopeMetadata.getScopedProxyMode());
}
@Test
- public void testThatResolveScopeMetadataDoesApplyScopedProxyModeToAPrototype() {
- this.scopeMetadataResolver = new AnnotationScopeMetadataResolver(ScopedProxyMode.INTERFACES);
+ public void resolveScopeMetadataShouldApplyScopedProxyModeToPrototype() {
+ this.scopeMetadataResolver = new AnnotationScopeMetadataResolver(INTERFACES);
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithPrototypeScope.class);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
assertEquals(BeanDefinition.SCOPE_PROTOTYPE, scopeMetadata.getScopeName());
- assertEquals(ScopedProxyMode.INTERFACES, scopeMetadata.getScopedProxyMode());
+ assertEquals(INTERFACES, scopeMetadata.getScopedProxyMode());
}
@Test
- public void testThatResolveScopeMetadataDoesReadScopedProxyModeFromTheAnnotation() {
+ public void resolveScopeMetadataShouldReadScopedProxyModeFromAnnotation() {
this.scopeMetadataResolver = new AnnotationScopeMetadataResolver();
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithScopedProxy.class);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
assertEquals("request", scopeMetadata.getScopeName());
- assertEquals(ScopedProxyMode.TARGET_CLASS, scopeMetadata.getScopedProxyMode());
+ assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode());
}
@Test
- public void testCustomRequestScope() {
+ public void customRequestScope() {
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithCustomRequestScope.class);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
assertEquals("request", scopeMetadata.getScopeName());
- assertEquals(ScopedProxyMode.NO, scopeMetadata.getScopedProxyMode());
+ assertEquals(NO, scopeMetadata.getScopedProxyMode());
}
@Test
- public void testCustomRequestScopeViaAsm() throws IOException {
+ public void customRequestScopeViaAsm() throws IOException {
MetadataReaderFactory readerFactory = new SimpleMetadataReaderFactory();
MetadataReader reader = readerFactory.getMetadataReader(AnnotatedWithCustomRequestScope.class.getName());
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(reader.getAnnotationMetadata());
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
assertEquals("request", scopeMetadata.getScopeName());
- assertEquals(ScopedProxyMode.NO, scopeMetadata.getScopedProxyMode());
+ assertEquals(NO, scopeMetadata.getScopedProxyMode());
}
@Test
- public void testCustomRequestScopeWithAttribute() {
- AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(AnnotatedWithCustomRequestScopeWithAttribute.class);
+ public void customRequestScopeWithAttribute() {
+ AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(
+ AnnotatedWithCustomRequestScopeWithAttributeOverride.class);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
assertEquals("request", scopeMetadata.getScopeName());
- assertEquals(ScopedProxyMode.TARGET_CLASS, scopeMetadata.getScopedProxyMode());
+ assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode());
}
@Test
- public void testCustomRequestScopeWithAttributeViaAsm() throws IOException {
+ public void customRequestScopeWithAttributeViaAsm() throws IOException {
MetadataReaderFactory readerFactory = new SimpleMetadataReaderFactory();
- MetadataReader reader = readerFactory.getMetadataReader(AnnotatedWithCustomRequestScopeWithAttribute.class.getName());
+ MetadataReader reader = readerFactory.getMetadataReader(AnnotatedWithCustomRequestScopeWithAttributeOverride.class.getName());
AnnotatedBeanDefinition bd = new AnnotatedGenericBeanDefinition(reader.getAnnotationMetadata());
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(bd);
assertNotNull("resolveScopeMetadata(..) must *never* return null.", scopeMetadata);
assertEquals("request", scopeMetadata.getScopeName());
- assertEquals(ScopedProxyMode.TARGET_CLASS, scopeMetadata.getScopedProxyMode());
+ assertEquals(TARGET_CLASS, scopeMetadata.getScopedProxyMode());
}
- @Test(expected=IllegalArgumentException.class)
- public void testCtorWithNullScopedProxyMode() {
+ @Test(expected = IllegalArgumentException.class)
+ public void ctorWithNullScopedProxyMode() {
new AnnotationScopeMetadataResolver(null);
}
- @Test(expected=IllegalArgumentException.class)
- public void testSetScopeAnnotationTypeWithNullType() {
+ @Test(expected = IllegalArgumentException.class)
+ public void setScopeAnnotationTypeWithNullType() {
scopeMetadataResolver.setScopeAnnotationType(null);
}
- @Scope("singleton")
- private static final class AnnotatedWithSingletonScope {
- }
-
- @Scope("prototype")
- private static final class AnnotatedWithPrototypeScope {
- }
-
- @Scope(value="request", proxyMode = ScopedProxyMode.TARGET_CLASS)
- private static final class AnnotatedWithScopedProxy {
+ @Retention(RetentionPolicy.RUNTIME)
+ @Scope("request")
+ @interface CustomRequestScope {
}
-
- @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Scope("request")
- public @interface CustomRequestScope {
+ @interface CustomRequestScopeWithAttributeOverride {
+ ScopedProxyMode proxyMode();
}
- @CustomRequestScope
- private static final class AnnotatedWithCustomRequestScope {
+ @Scope("singleton")
+ private static class AnnotatedWithSingletonScope {
}
+ @Scope("prototype")
+ private static class AnnotatedWithPrototypeScope {
+ }
- @Target({ElementType.TYPE, ElementType.METHOD})
- @Retention(RetentionPolicy.RUNTIME)
- @Scope("request")
- public @interface CustomRequestScopeWithAttribute {
+ @Scope(name = "request", proxyMode = TARGET_CLASS)
+ private static class AnnotatedWithScopedProxy {
+ }
- ScopedProxyMode proxyMode();
+ @CustomRequestScope
+ private static class AnnotatedWithCustomRequestScope {
}
- @CustomRequestScopeWithAttribute(proxyMode = ScopedProxyMode.TARGET_CLASS)
- private static final class AnnotatedWithCustomRequestScopeWithAttribute {
+ @CustomRequestScopeWithAttributeOverride(proxyMode = TARGET_CLASS)
+ private static class AnnotatedWithCustomRequestScopeWithAttributeOverride {
}
}
diff --git a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java
index 251fcabd0b1..502524c18fc 100644
--- a/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java
+++ b/spring-context/src/test/java/org/springframework/context/annotation/ConfigurationClassPostProcessorTests.java
@@ -787,7 +787,7 @@ public class ConfigurationClassPostProcessorTests {
public static class ScopedProxyRepositoryConfiguration {
@Bean
- @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
+ @Scope(name = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Repository