support scope meta-annotations on factory methods as well

This commit is contained in:
Juergen Hoeller 2009-07-21 14:23:25 +00:00
parent 54285ea57c
commit ec1f0e6211
5 changed files with 41 additions and 31 deletions

View File

@ -63,7 +63,7 @@ import org.springframework.beans.factory.annotation.Autowire;
* @see Primary * @see Primary
* @see org.springframework.context.annotation.Scope * @see org.springframework.context.annotation.Scope
*/ */
@Target(ElementType.METHOD) @Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface Bean { public @interface Bean {

View File

@ -182,8 +182,8 @@ class ConfigurationClassBeanDefinitionReader {
// consider scoping // consider scoping
ScopedProxyMode proxyMode = ScopedProxyMode.NO; ScopedProxyMode proxyMode = ScopedProxyMode.NO;
if (metadata.hasAnnotation(Scope.class.getName())) { Map<String, Object> scopeAttributes = metadata.getAnnotationAttributes(Scope.class.getName());
Map<String, Object> scopeAttributes = metadata.getAnnotationAttributes(Scope.class.getName()); if (scopeAttributes != null) {
beanDef.setScope((String) scopeAttributes.get("value")); beanDef.setScope((String) scopeAttributes.get("value"));
proxyMode = (ScopedProxyMode) scopeAttributes.get("proxyMode"); proxyMode = (ScopedProxyMode) scopeAttributes.get("proxyMode");
if (proxyMode == ScopedProxyMode.DEFAULT) { if (proxyMode == ScopedProxyMode.DEFAULT) {
@ -195,7 +195,7 @@ class ConfigurationClassBeanDefinitionReader {
BeanDefinition beanDefToRegister = beanDef; BeanDefinition beanDefToRegister = beanDef;
if (proxyMode != ScopedProxyMode.NO) { if (proxyMode != ScopedProxyMode.NO) {
BeanDefinitionHolder proxyDef = ScopedProxyCreator.createScopedProxy( 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(); beanDefToRegister = proxyDef.getBeanDefinition();
} }

View File

@ -72,7 +72,7 @@ class ConfigurationClassEnhancer {
// handling a @Bean-annotated method; otherwise, return index of the NoOp callback. // handling a @Bean-annotated method; otherwise, return index of the NoOp callback.
callbackFilter = new CallbackFilter() { callbackFilter = new CallbackFilter() {
public int accept(Method candidateMethod) { 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(); String beanName = method.getName();
// check to see if the user has explicitly set the bean name // check to see if the user has explicitly set the bean name
Bean bean = method.getAnnotation(Bean.class); Bean bean = AnnotationUtils.findAnnotation(method, Bean.class);
if(bean != null && bean.name().length > 0) { if (bean != null && bean.name().length > 0) {
beanName = bean.name()[0]; beanName = bean.name()[0];
} }

View File

@ -57,10 +57,9 @@ public @interface Scope {
/** /**
* Specifies whether a component should be configured as a scoped proxy * Specifies whether a component should be configured as a scoped proxy
* and if so, whether the proxy should be interface-based or subclass-based. * and if so, whether the proxy should be interface-based or subclass-based.
* <p>Defaults to {@link ScopedProxyMode#NO}, indicating no scoped proxy * <p>Defaults to {@link ScopedProxyMode#NO}, indicating that no scoped
* should be created. * proxy should be created.
* <p>Analogous to {@literal <aop:scoped-proxy/>} support in Spring XML. Valid * <p>Analogous to {@literal <aop:scoped-proxy/>} support in Spring XML.
* only in conjunction with a non-singleton, non-prototype {@link #value()}.
*/ */
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT; ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;

View File

@ -16,10 +16,13 @@
package org.springframework.context.annotation.configuration; 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.HashMap;
import java.util.Map; import java.util.Map;
import static org.hamcrest.CoreMatchers.*;
import org.junit.After; import org.junit.After;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import org.junit.Before; import org.junit.Before;
@ -29,8 +32,8 @@ import test.beans.TestBean;
import org.springframework.aop.scope.ScopedObject; import org.springframework.aop.scope.ScopedObject;
import org.springframework.beans.factory.ObjectFactory; 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.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.context.annotation.ConfigurationClassPostProcessor;
@ -67,13 +70,13 @@ public class ScopingTests {
ctx = null; ctx = null;
customScope = null; customScope = null;
} }
private GenericApplicationContext createContext(org.springframework.beans.factory.config.Scope customScope, Class<?> configClass) { private GenericApplicationContext createContext(org.springframework.beans.factory.config.Scope customScope, Class<?> configClass) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
if(customScope != null) if (customScope != null) {
beanFactory.registerScope(SCOPE, customScope); beanFactory.registerScope(SCOPE, customScope);
beanFactory.registerBeanDefinition("config", }
rootBeanDefinition(configClass).getBeanDefinition()); beanFactory.registerBeanDefinition("config", new RootBeanDefinition(configClass));
GenericApplicationContext ctx = new GenericApplicationContext(beanFactory); GenericApplicationContext ctx = new GenericApplicationContext(beanFactory);
ctx.addBeanFactoryPostProcessor(new ConfigurationClassPostProcessor()); ctx.addBeanFactoryPostProcessor(new ConfigurationClassPostProcessor());
ctx.refresh(); ctx.refresh();
@ -187,10 +190,9 @@ public class ScopingTests {
@Test @Test
public void testScopedConfigurationBeanDefinitionCount() throws Exception { public void testScopedConfigurationBeanDefinitionCount() throws Exception {
// count the beans // count the beans
// 6 @Beans + 1 Configuration + 2 scoped proxy // 6 @Beans + 1 Configuration + 2 scoped proxy
assertThat(ctx.getBeanDefinitionCount(), equalTo(9)); assertEquals(9, ctx.getBeanDefinitionCount());
} }
// /** // /**
@ -294,14 +296,16 @@ public class ScopingTests {
@Configuration @Configuration
public static class InvalidProxyOnPredefinedScopesConfiguration { public static class InvalidProxyOnPredefinedScopesConfiguration {
@Bean @Scope(proxyMode=ScopedProxyMode.INTERFACES) @Bean @Scope(proxyMode=ScopedProxyMode.INTERFACES)
public Object invalidProxyOnPredefinedScopes() { return new Object(); } public Object invalidProxyOnPredefinedScopes() { return new Object(); }
} }
@Configuration @Configuration
public static class ScopedConfigurationClass { public static class ScopedConfigurationClass {
@Bean @Bean
@Scope(SCOPE) @MyScope
public TestBean scopedClass() { public TestBean scopedClass() {
TestBean tb = new TestBean(); TestBean tb = new TestBean();
tb.setName(flag); tb.setName(flag);
@ -309,23 +313,21 @@ public class ScopingTests {
} }
@Bean @Bean
@Scope(SCOPE) @MyScope
public ITestBean scopedInterface() { public ITestBean scopedInterface() {
TestBean tb = new TestBean(); TestBean tb = new TestBean();
tb.setName(flag); tb.setName(flag);
return tb; return tb;
} }
@Bean @MyProxiedScope
@Scope(value=SCOPE, proxyMode=ScopedProxyMode.TARGET_CLASS)
public ITestBean scopedProxyInterface() { public ITestBean scopedProxyInterface() {
TestBean tb = new TestBean(); TestBean tb = new TestBean();
tb.setName(flag); tb.setName(flag);
return tb; return tb;
} }
@Bean @MyProxiedScope
@Scope(value=SCOPE, proxyMode=ScopedProxyMode.TARGET_CLASS)
public TestBean scopedProxyClass() { public TestBean scopedProxyClass() {
TestBean tb = new TestBean(); TestBean tb = new TestBean();
tb.setName(flag); 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. * Simple scope implementation which creates object based on a flag.
* @author Costin Leau * @author Costin Leau
@ -359,11 +376,6 @@ public class ScopingTests {
private Map<String, Object> beans = new HashMap<String, Object>(); private Map<String, Object> beans = new HashMap<String, Object>();
/*
* (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) { public Object get(String name, ObjectFactory<?> objectFactory) {
if (createNewScope) { if (createNewScope) {
beans.clear(); beans.clear();
@ -394,7 +406,6 @@ public class ScopingTests {
} }
public Object resolveContextualObject(String key) { public Object resolveContextualObject(String key) {
// TODO Auto-generated method stub
return null; return null;
} }
} }