Introduce alias for 'value' attribute in @Scope
Issue: SPR-11393
This commit is contained in:
parent
6b7c1d72e8
commit
2d23f42609
|
|
@ -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.
|
||||
*
|
||||
* <p>The exact type of annotation that is checked for is configurable via the
|
||||
* {@link #setScopeAnnotationType(Class)} property.
|
||||
* <p>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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
* <p>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.
|
||||
* <p>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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Scope("request")
|
||||
public @interface CustomRequestScope {
|
||||
@interface CustomRequestScope {
|
||||
}
|
||||
|
||||
@CustomRequestScope
|
||||
private static final class AnnotatedWithCustomRequestScope {
|
||||
}
|
||||
|
||||
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Scope("request")
|
||||
public @interface CustomRequestScopeWithAttribute {
|
||||
|
||||
@interface CustomRequestScopeWithAttributeOverride {
|
||||
ScopedProxyMode proxyMode();
|
||||
}
|
||||
|
||||
@CustomRequestScopeWithAttribute(proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
private static final class AnnotatedWithCustomRequestScopeWithAttribute {
|
||||
@Scope("singleton")
|
||||
private static class AnnotatedWithSingletonScope {
|
||||
}
|
||||
|
||||
@Scope("prototype")
|
||||
private static class AnnotatedWithPrototypeScope {
|
||||
}
|
||||
|
||||
@Scope(name = "request", proxyMode = TARGET_CLASS)
|
||||
private static class AnnotatedWithScopedProxy {
|
||||
}
|
||||
|
||||
@CustomRequestScope
|
||||
private static class AnnotatedWithCustomRequestScope {
|
||||
}
|
||||
|
||||
@CustomRequestScopeWithAttributeOverride(proxyMode = TARGET_CLASS)
|
||||
private static class AnnotatedWithCustomRequestScopeWithAttributeOverride {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String> stringRepo() {
|
||||
return new Repository<String>() {
|
||||
@Override
|
||||
|
|
@ -798,7 +798,7 @@ public class ConfigurationClassPostProcessorTests {
|
|||
}
|
||||
|
||||
@Bean
|
||||
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
@Scope(name = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
public Repository<Integer> integerRepo() {
|
||||
return new Repository<Integer>() {
|
||||
@Override
|
||||
|
|
|
|||
Loading…
Reference in New Issue