Common annotation processing for imported and nested classes within configuration classes
Issue: SPR-12486
This commit is contained in:
parent
c94d584f37
commit
c5c5473d44
|
|
@ -72,6 +72,8 @@ class ConfigurationClassBeanDefinitionReader {
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(ConfigurationClassBeanDefinitionReader.class);
|
private static final Log logger = LogFactory.getLog(ConfigurationClassBeanDefinitionReader.class);
|
||||||
|
|
||||||
|
private static final ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
|
||||||
|
|
||||||
private final BeanDefinitionRegistry registry;
|
private final BeanDefinitionRegistry registry;
|
||||||
|
|
||||||
private final SourceExtractor sourceExtractor;
|
private final SourceExtractor sourceExtractor;
|
||||||
|
|
@ -154,10 +156,16 @@ class ConfigurationClassBeanDefinitionReader {
|
||||||
*/
|
*/
|
||||||
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
|
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
|
||||||
AnnotationMetadata metadata = configClass.getMetadata();
|
AnnotationMetadata metadata = configClass.getMetadata();
|
||||||
BeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
|
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
|
||||||
|
|
||||||
if (ConfigurationClassUtils.checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
|
if (ConfigurationClassUtils.checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
|
||||||
|
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
|
||||||
|
configBeanDef.setScope(scopeMetadata.getScopeName());
|
||||||
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
|
String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
|
||||||
this.registry.registerBeanDefinition(configBeanName, configBeanDef);
|
AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);
|
||||||
|
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
|
||||||
|
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
|
||||||
|
this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
|
||||||
configClass.setBeanName(configBeanName);
|
configClass.setBeanName(configBeanName);
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(String.format("Registered bean definition for imported @Configuration class %s", configBeanName));
|
logger.debug(String.format("Registered bean definition for imported @Configuration class %s", configBeanName));
|
||||||
|
|
|
||||||
|
|
@ -58,12 +58,15 @@ public class NestedConfigurationClassTests {
|
||||||
ctx.register(L0Config.class);
|
ctx.register(L0Config.class);
|
||||||
ctx.refresh();
|
ctx.refresh();
|
||||||
|
|
||||||
|
assertFalse(ctx.getBeanFactory().containsSingleton("nestedConfigurationClassTests.L0Config"));
|
||||||
ctx.getBean(L0Config.class);
|
ctx.getBean(L0Config.class);
|
||||||
ctx.getBean("l0Bean");
|
ctx.getBean("l0Bean");
|
||||||
|
|
||||||
|
assertTrue(ctx.getBeanFactory().containsSingleton(L0Config.L1Config.class.getName()));
|
||||||
ctx.getBean(L0Config.L1Config.class);
|
ctx.getBean(L0Config.L1Config.class);
|
||||||
ctx.getBean("l1Bean");
|
ctx.getBean("l1Bean");
|
||||||
|
|
||||||
|
assertFalse(ctx.getBeanFactory().containsSingleton(L0Config.L1Config.L2Config.class.getName()));
|
||||||
ctx.getBean(L0Config.L1Config.L2Config.class);
|
ctx.getBean(L0Config.L1Config.L2Config.class);
|
||||||
ctx.getBean("l2Bean");
|
ctx.getBean("l2Bean");
|
||||||
|
|
||||||
|
|
@ -71,14 +74,38 @@ public class NestedConfigurationClassTests {
|
||||||
assertThat(ctx.getBean("overrideBean", TestBean.class).getName(), is("override-l0"));
|
assertThat(ctx.getBean("overrideBean", TestBean.class).getName(), is("override-l0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void twoLevelsInLiteMode() {
|
||||||
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||||
|
ctx.register(L0ConfigLight.class);
|
||||||
|
ctx.refresh();
|
||||||
|
|
||||||
|
assertFalse(ctx.getBeanFactory().containsSingleton("nestedConfigurationClassTests.L0ConfigLight"));
|
||||||
|
ctx.getBean(L0ConfigLight.class);
|
||||||
|
ctx.getBean("l0Bean");
|
||||||
|
|
||||||
|
assertTrue(ctx.getBeanFactory().containsSingleton(L0ConfigLight.L1ConfigLight.class.getName()));
|
||||||
|
ctx.getBean(L0ConfigLight.L1ConfigLight.class);
|
||||||
|
ctx.getBean("l1Bean");
|
||||||
|
|
||||||
|
assertFalse(ctx.getBeanFactory().containsSingleton(L0ConfigLight.L1ConfigLight.L2ConfigLight.class.getName()));
|
||||||
|
ctx.getBean(L0ConfigLight.L1ConfigLight.L2ConfigLight.class);
|
||||||
|
ctx.getBean("l2Bean");
|
||||||
|
|
||||||
|
// ensure that override order is correct
|
||||||
|
assertThat(ctx.getBean("overrideBean", TestBean.class).getName(), is("override-l0"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void twoLevelsDeepWithInheritance() {
|
public void twoLevelsDeepWithInheritance() {
|
||||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||||
ctx.register(S1Config.class);
|
ctx.register(S1Config.class);
|
||||||
ctx.refresh();
|
ctx.refresh();
|
||||||
|
|
||||||
ctx.getBean(S1Config.class);
|
S1Config config = ctx.getBean(S1Config.class);
|
||||||
ctx.getBean("l0Bean");
|
assertTrue(config != ctx.getBean(S1Config.class));
|
||||||
|
TestBean tb = ctx.getBean("l0Bean", TestBean.class);
|
||||||
|
assertTrue(tb == ctx.getBean("l0Bean", TestBean.class));
|
||||||
|
|
||||||
ctx.getBean(L0Config.L1Config.class);
|
ctx.getBean(L0Config.L1Config.class);
|
||||||
ctx.getBean("l1Bean");
|
ctx.getBean("l1Bean");
|
||||||
|
|
@ -86,27 +113,71 @@ public class NestedConfigurationClassTests {
|
||||||
ctx.getBean(L0Config.L1Config.L2Config.class);
|
ctx.getBean(L0Config.L1Config.L2Config.class);
|
||||||
ctx.getBean("l2Bean");
|
ctx.getBean("l2Bean");
|
||||||
|
|
||||||
// ensure that override order is correct
|
// ensure that override order is correct and that it is a singleton
|
||||||
assertThat(ctx.getBean("overrideBean", TestBean.class).getName(), is("override-s1"));
|
TestBean ob = ctx.getBean("overrideBean", TestBean.class);
|
||||||
|
assertThat(ob.getName(), is("override-s1"));
|
||||||
|
assertTrue(ob == ctx.getBean("overrideBean", TestBean.class));
|
||||||
|
|
||||||
|
TestBean pb1 = ctx.getBean("prototypeBean", TestBean.class);
|
||||||
|
TestBean pb2 = ctx.getBean("prototypeBean", TestBean.class);
|
||||||
|
assertTrue(pb1 != pb2);
|
||||||
|
assertTrue(pb1.getFriends().iterator().next() != pb2.getFriends().iterator().next());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void twoLevelsInLiteMode() {
|
public void twoLevelsDeepWithInheritanceThroughImport() {
|
||||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||||
ctx.register(L0ConfigLight.class);
|
ctx.register(S1Importer.class);
|
||||||
ctx.refresh();
|
ctx.refresh();
|
||||||
|
|
||||||
ctx.getBean(L0ConfigLight.class);
|
S1Config config = ctx.getBean(S1Config.class);
|
||||||
ctx.getBean("l0Bean");
|
assertTrue(config != ctx.getBean(S1Config.class));
|
||||||
|
TestBean tb = ctx.getBean("l0Bean", TestBean.class);
|
||||||
|
assertTrue(tb == ctx.getBean("l0Bean", TestBean.class));
|
||||||
|
|
||||||
ctx.getBean(L0ConfigLight.L1ConfigLight.class);
|
ctx.getBean(L0Config.L1Config.class);
|
||||||
ctx.getBean("l1Bean");
|
ctx.getBean("l1Bean");
|
||||||
|
|
||||||
ctx.getBean(L0ConfigLight.L1ConfigLight.L2ConfigLight.class);
|
ctx.getBean(L0Config.L1Config.L2Config.class);
|
||||||
ctx.getBean("l2Bean");
|
ctx.getBean("l2Bean");
|
||||||
|
|
||||||
// ensure that override order is correct
|
// ensure that override order is correct and that it is a singleton
|
||||||
assertThat(ctx.getBean("overrideBean", TestBean.class).getName(), is("override-l0"));
|
TestBean ob = ctx.getBean("overrideBean", TestBean.class);
|
||||||
|
assertThat(ob.getName(), is("override-s1"));
|
||||||
|
assertTrue(ob == ctx.getBean("overrideBean", TestBean.class));
|
||||||
|
|
||||||
|
TestBean pb1 = ctx.getBean("prototypeBean", TestBean.class);
|
||||||
|
TestBean pb2 = ctx.getBean("prototypeBean", TestBean.class);
|
||||||
|
assertTrue(pb1 != pb2);
|
||||||
|
assertTrue(pb1.getFriends().iterator().next() != pb2.getFriends().iterator().next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void twoLevelsDeepWithInheritanceAndScopedProxy() {
|
||||||
|
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||||
|
ctx.register(S1ImporterWithProxy.class);
|
||||||
|
ctx.refresh();
|
||||||
|
|
||||||
|
S1ConfigWithProxy config = ctx.getBean(S1ConfigWithProxy.class);
|
||||||
|
assertTrue(config == ctx.getBean(S1ConfigWithProxy.class));
|
||||||
|
TestBean tb = ctx.getBean("l0Bean", TestBean.class);
|
||||||
|
assertTrue(tb == ctx.getBean("l0Bean", TestBean.class));
|
||||||
|
|
||||||
|
ctx.getBean(L0Config.L1Config.class);
|
||||||
|
ctx.getBean("l1Bean");
|
||||||
|
|
||||||
|
ctx.getBean(L0Config.L1Config.L2Config.class);
|
||||||
|
ctx.getBean("l2Bean");
|
||||||
|
|
||||||
|
// ensure that override order is correct and that it is a singleton
|
||||||
|
TestBean ob = ctx.getBean("overrideBean", TestBean.class);
|
||||||
|
assertThat(ob.getName(), is("override-s1"));
|
||||||
|
assertTrue(ob == ctx.getBean("overrideBean", TestBean.class));
|
||||||
|
|
||||||
|
TestBean pb1 = ctx.getBean("prototypeBean", TestBean.class);
|
||||||
|
TestBean pb2 = ctx.getBean("prototypeBean", TestBean.class);
|
||||||
|
assertTrue(pb1 != pb2);
|
||||||
|
assertTrue(pb1.getFriends().iterator().next() != pb2.getFriends().iterator().next());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -115,21 +186,34 @@ public class NestedConfigurationClassTests {
|
||||||
ctx.register(L0ConfigEmpty.class);
|
ctx.register(L0ConfigEmpty.class);
|
||||||
ctx.refresh();
|
ctx.refresh();
|
||||||
|
|
||||||
ctx.getBean(L0ConfigEmpty.class);
|
assertFalse(ctx.getBeanFactory().containsSingleton("l0ConfigEmpty"));
|
||||||
ctx.getBean(L0ConfigEmpty.L1ConfigEmpty.class);
|
Object l0i1 = ctx.getBean(L0ConfigEmpty.class);
|
||||||
ctx.getBean(L0ConfigEmpty.L1ConfigEmpty.L2ConfigEmpty.class);
|
Object l0i2 = ctx.getBean(L0ConfigEmpty.class);
|
||||||
|
assertTrue(l0i1 == l0i2);
|
||||||
|
|
||||||
|
Object l1i1 = ctx.getBean(L0ConfigEmpty.L1ConfigEmpty.class);
|
||||||
|
Object l1i2 = ctx.getBean(L0ConfigEmpty.L1ConfigEmpty.class);
|
||||||
|
assertTrue(l1i1 != l1i2);
|
||||||
|
|
||||||
|
Object l2i1 = ctx.getBean(L0ConfigEmpty.L1ConfigEmpty.L2ConfigEmpty.class);
|
||||||
|
Object l2i2 = ctx.getBean(L0ConfigEmpty.L1ConfigEmpty.L2ConfigEmpty.class);
|
||||||
|
assertTrue(l2i1 == l2i2);
|
||||||
|
assertNotEquals(l2i1.toString(), l2i2.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Lazy
|
||||||
static class L0Config {
|
static class L0Config {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Lazy
|
||||||
public TestBean l0Bean() {
|
public TestBean l0Bean() {
|
||||||
return new TestBean("l0");
|
return new TestBean("l0");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Lazy
|
||||||
public TestBean overrideBean() {
|
public TestBean overrideBean() {
|
||||||
return new TestBean("override-l0");
|
return new TestBean("override-l0");
|
||||||
}
|
}
|
||||||
|
|
@ -148,14 +232,17 @@ public class NestedConfigurationClassTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Lazy
|
||||||
protected static class L2Config {
|
protected static class L2Config {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Lazy
|
||||||
public TestBean l2Bean() {
|
public TestBean l2Bean() {
|
||||||
return new TestBean("l2");
|
return new TestBean("l2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Lazy
|
||||||
public TestBean overrideBean() {
|
public TestBean overrideBean() {
|
||||||
return new TestBean("override-l2");
|
return new TestBean("override-l2");
|
||||||
}
|
}
|
||||||
|
|
@ -165,14 +252,17 @@ public class NestedConfigurationClassTests {
|
||||||
|
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@Lazy
|
||||||
static class L0ConfigLight {
|
static class L0ConfigLight {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Lazy
|
||||||
public TestBean l0Bean() {
|
public TestBean l0Bean() {
|
||||||
return new TestBean("l0");
|
return new TestBean("l0");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Lazy
|
||||||
public TestBean overrideBean() {
|
public TestBean overrideBean() {
|
||||||
return new TestBean("override-l0");
|
return new TestBean("override-l0");
|
||||||
}
|
}
|
||||||
|
|
@ -191,14 +281,17 @@ public class NestedConfigurationClassTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@Lazy
|
||||||
protected static class L2ConfigLight {
|
protected static class L2ConfigLight {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Lazy
|
||||||
public TestBean l2Bean() {
|
public TestBean l2Bean() {
|
||||||
return new TestBean("l2");
|
return new TestBean("l2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@Lazy
|
||||||
public TestBean overrideBean() {
|
public TestBean overrideBean() {
|
||||||
return new TestBean("override-l2");
|
return new TestBean("override-l2");
|
||||||
}
|
}
|
||||||
|
|
@ -207,20 +300,8 @@ public class NestedConfigurationClassTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Component
|
|
||||||
static class L0ConfigEmpty {
|
|
||||||
|
|
||||||
@Component
|
|
||||||
static class L1ConfigEmpty {
|
|
||||||
|
|
||||||
@Component
|
|
||||||
protected static class L2ConfigEmpty {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@Scope("prototype")
|
||||||
static class S1Config extends L0Config {
|
static class S1Config extends L0Config {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -228,6 +309,60 @@ public class NestedConfigurationClassTests {
|
||||||
public TestBean overrideBean() {
|
public TestBean overrideBean() {
|
||||||
return new TestBean("override-s1");
|
return new TestBean("override-s1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Scope("prototype")
|
||||||
|
public TestBean prototypeBean() {
|
||||||
|
TestBean tb = new TestBean("override-s1");
|
||||||
|
tb.getFriends().add(this);
|
||||||
|
return tb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||||
|
static class S1ConfigWithProxy extends L0Config {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Bean
|
||||||
|
public TestBean overrideBean() {
|
||||||
|
return new TestBean("override-s1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Scope("prototype")
|
||||||
|
public TestBean prototypeBean() {
|
||||||
|
TestBean tb = new TestBean("override-s1");
|
||||||
|
tb.getFriends().add(this);
|
||||||
|
return tb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Import(S1Config.class)
|
||||||
|
static class S1Importer {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Import(S1ConfigWithProxy.class)
|
||||||
|
static class S1ImporterWithProxy {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Lazy
|
||||||
|
static class L0ConfigEmpty {
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope("prototype")
|
||||||
|
static class L1ConfigEmpty {
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||||
|
protected static class L2ConfigEmpty {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue