diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java index 57d10141cd9..cc8c2187841 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/Bean.java @@ -63,7 +63,7 @@ import org.springframework.beans.factory.annotation.Autowire; * @see Primary * @see org.springframework.context.annotation.Scope */ -@Target(ElementType.METHOD) +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Bean { diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java index 0b7af9b1d25..6419d616121 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java @@ -182,8 +182,8 @@ class ConfigurationClassBeanDefinitionReader { // consider scoping ScopedProxyMode proxyMode = ScopedProxyMode.NO; - if (metadata.hasAnnotation(Scope.class.getName())) { - Map scopeAttributes = metadata.getAnnotationAttributes(Scope.class.getName()); + Map scopeAttributes = metadata.getAnnotationAttributes(Scope.class.getName()); + if (scopeAttributes != null) { beanDef.setScope((String) scopeAttributes.get("value")); proxyMode = (ScopedProxyMode) scopeAttributes.get("proxyMode"); if (proxyMode == ScopedProxyMode.DEFAULT) { @@ -195,7 +195,7 @@ class ConfigurationClassBeanDefinitionReader { BeanDefinition beanDefToRegister = beanDef; if (proxyMode != ScopedProxyMode.NO) { BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy( - new BeanDefinitionHolder(beanDef, beanName), registry, proxyMode == ScopedProxyMode.TARGET_CLASS); + new BeanDefinitionHolder(beanDef, beanName), this.registry, proxyMode == ScopedProxyMode.TARGET_CLASS); beanDefToRegister = proxyDef.getBeanDefinition(); } diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java index 9234b36403a..d1cfe3ead35 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/ConfigurationClassEnhancer.java @@ -72,7 +72,7 @@ class ConfigurationClassEnhancer { // handling a @Bean-annotated method; otherwise, return index of the NoOp callback. callbackFilter = new CallbackFilter() { public int accept(Method candidateMethod) { - return (AnnotationUtils.findAnnotation(candidateMethod, Bean.class) != null) ? 0 : 1; + return (AnnotationUtils.findAnnotation(candidateMethod, Bean.class) != null ? 0 : 1); } }; } @@ -149,8 +149,8 @@ class ConfigurationClassEnhancer { String beanName = method.getName(); // check to see if the user has explicitly set the bean name - Bean bean = method.getAnnotation(Bean.class); - if(bean != null && bean.name().length > 0) { + Bean bean = AnnotationUtils.findAnnotation(method, Bean.class); + if (bean != null && bean.name().length > 0) { beanName = bean.name()[0]; } diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/Scope.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/Scope.java index 50f78e72360..55409be3139 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/Scope.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/Scope.java @@ -57,10 +57,9 @@ public @interface Scope { /** * Specifies whether a component should be configured as a scoped proxy * and if so, whether the proxy should be interface-based or subclass-based. - *

Defaults to {@link ScopedProxyMode#NO}, indicating no scoped proxy - * should be created. - *

Analogous to {@literal } support in Spring XML. Valid - * only in conjunction with a non-singleton, non-prototype {@link #value()}. + *

Defaults to {@link ScopedProxyMode#NO}, indicating that no scoped + * proxy should be created. + *

Analogous to {@literal } support in Spring XML. */ ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT; diff --git a/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java b/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java index 66ef9894719..3094e2553e2 100644 --- a/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java +++ b/org.springframework.context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java @@ -16,10 +16,13 @@ package org.springframework.context.annotation.configuration; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.util.HashMap; import java.util.Map; -import static org.hamcrest.CoreMatchers.*; import org.junit.After; import static org.junit.Assert.*; import org.junit.Before; @@ -29,8 +32,8 @@ import test.beans.TestBean; import org.springframework.aop.scope.ScopedObject; import org.springframework.beans.factory.ObjectFactory; -import static org.springframework.beans.factory.support.BeanDefinitionBuilder.*; import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ConfigurationClassPostProcessor; @@ -67,13 +70,13 @@ public class ScopingTests { ctx = null; customScope = null; } - + private GenericApplicationContext createContext(org.springframework.beans.factory.config.Scope customScope, Class configClass) { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); - if(customScope != null) + if (customScope != null) { beanFactory.registerScope(SCOPE, customScope); - beanFactory.registerBeanDefinition("config", - rootBeanDefinition(configClass).getBeanDefinition()); + } + beanFactory.registerBeanDefinition("config", new RootBeanDefinition(configClass)); GenericApplicationContext ctx = new GenericApplicationContext(beanFactory); ctx.addBeanFactoryPostProcessor(new ConfigurationClassPostProcessor()); ctx.refresh(); @@ -187,10 +190,9 @@ public class ScopingTests { @Test public void testScopedConfigurationBeanDefinitionCount() throws Exception { - // count the beans // 6 @Beans + 1 Configuration + 2 scoped proxy - assertThat(ctx.getBeanDefinitionCount(), equalTo(9)); + assertEquals(9, ctx.getBeanDefinitionCount()); } // /** @@ -294,14 +296,16 @@ public class ScopingTests { @Configuration public static class InvalidProxyOnPredefinedScopesConfiguration { + @Bean @Scope(proxyMode=ScopedProxyMode.INTERFACES) public Object invalidProxyOnPredefinedScopes() { return new Object(); } } @Configuration public static class ScopedConfigurationClass { + @Bean - @Scope(SCOPE) + @MyScope public TestBean scopedClass() { TestBean tb = new TestBean(); tb.setName(flag); @@ -309,23 +313,21 @@ public class ScopingTests { } @Bean - @Scope(SCOPE) + @MyScope public ITestBean scopedInterface() { TestBean tb = new TestBean(); tb.setName(flag); return tb; } - @Bean - @Scope(value=SCOPE, proxyMode=ScopedProxyMode.TARGET_CLASS) + @MyProxiedScope public ITestBean scopedProxyInterface() { TestBean tb = new TestBean(); tb.setName(flag); return tb; } - @Bean - @Scope(value=SCOPE, proxyMode=ScopedProxyMode.TARGET_CLASS) + @MyProxiedScope public TestBean scopedProxyClass() { TestBean tb = new TestBean(); tb.setName(flag); @@ -348,6 +350,21 @@ public class ScopingTests { } + @Target({ElementType.METHOD}) + @Retention(RetentionPolicy.RUNTIME) + @Scope(SCOPE) + @interface MyScope { + } + + + @Target({ElementType.METHOD}) + @Retention(RetentionPolicy.RUNTIME) + @Bean + @Scope(value=SCOPE, proxyMode=ScopedProxyMode.TARGET_CLASS) + @interface MyProxiedScope { + } + + /** * Simple scope implementation which creates object based on a flag. * @author Costin Leau @@ -359,11 +376,6 @@ public class ScopingTests { private Map beans = new HashMap(); - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.config.Scope#get(java.lang.String, - * org.springframework.beans.factory.ObjectFactory) - */ public Object get(String name, ObjectFactory objectFactory) { if (createNewScope) { beans.clear(); @@ -394,7 +406,6 @@ public class ScopingTests { } public Object resolveContextualObject(String key) { - // TODO Auto-generated method stub return null; } }