support scope meta-annotations on factory methods as well
This commit is contained in:
parent
54285ea57c
commit
ec1f0e6211
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue