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 ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
|
||||
|
||||
private final BeanDefinitionRegistry registry;
|
||||
|
||||
private final SourceExtractor sourceExtractor;
|
||||
|
|
@ -154,10 +156,16 @@ class ConfigurationClassBeanDefinitionReader {
|
|||
*/
|
||||
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
|
||||
AnnotationMetadata metadata = configClass.getMetadata();
|
||||
BeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
|
||||
AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);
|
||||
|
||||
if (ConfigurationClassUtils.checkConfigurationClassCandidate(configBeanDef, this.metadataReaderFactory)) {
|
||||
ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
|
||||
configBeanDef.setScope(scopeMetadata.getScopeName());
|
||||
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);
|
||||
if (logger.isDebugEnabled()) {
|
||||
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.refresh();
|
||||
|
||||
assertFalse(ctx.getBeanFactory().containsSingleton("nestedConfigurationClassTests.L0Config"));
|
||||
ctx.getBean(L0Config.class);
|
||||
ctx.getBean("l0Bean");
|
||||
|
||||
assertTrue(ctx.getBeanFactory().containsSingleton(L0Config.L1Config.class.getName()));
|
||||
ctx.getBean(L0Config.L1Config.class);
|
||||
ctx.getBean("l1Bean");
|
||||
|
||||
assertFalse(ctx.getBeanFactory().containsSingleton(L0Config.L1Config.L2Config.class.getName()));
|
||||
ctx.getBean(L0Config.L1Config.L2Config.class);
|
||||
ctx.getBean("l2Bean");
|
||||
|
||||
|
|
@ -71,14 +74,38 @@ public class NestedConfigurationClassTests {
|
|||
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
|
||||
public void twoLevelsDeepWithInheritance() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(S1Config.class);
|
||||
ctx.refresh();
|
||||
|
||||
ctx.getBean(S1Config.class);
|
||||
ctx.getBean("l0Bean");
|
||||
S1Config config = ctx.getBean(S1Config.class);
|
||||
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("l1Bean");
|
||||
|
|
@ -86,27 +113,71 @@ public class NestedConfigurationClassTests {
|
|||
ctx.getBean(L0Config.L1Config.L2Config.class);
|
||||
ctx.getBean("l2Bean");
|
||||
|
||||
// ensure that override order is correct
|
||||
assertThat(ctx.getBean("overrideBean", TestBean.class).getName(), is("override-s1"));
|
||||
// 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
|
||||
public void twoLevelsInLiteMode() {
|
||||
public void twoLevelsDeepWithInheritanceThroughImport() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(L0ConfigLight.class);
|
||||
ctx.register(S1Importer.class);
|
||||
ctx.refresh();
|
||||
|
||||
ctx.getBean(L0ConfigLight.class);
|
||||
ctx.getBean("l0Bean");
|
||||
S1Config config = ctx.getBean(S1Config.class);
|
||||
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(L0ConfigLight.L1ConfigLight.L2ConfigLight.class);
|
||||
ctx.getBean(L0Config.L1Config.L2Config.class);
|
||||
ctx.getBean("l2Bean");
|
||||
|
||||
// ensure that override order is correct
|
||||
assertThat(ctx.getBean("overrideBean", TestBean.class).getName(), is("override-l0"));
|
||||
// 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
|
||||
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
|
||||
|
|
@ -115,21 +186,34 @@ public class NestedConfigurationClassTests {
|
|||
ctx.register(L0ConfigEmpty.class);
|
||||
ctx.refresh();
|
||||
|
||||
ctx.getBean(L0ConfigEmpty.class);
|
||||
ctx.getBean(L0ConfigEmpty.L1ConfigEmpty.class);
|
||||
ctx.getBean(L0ConfigEmpty.L1ConfigEmpty.L2ConfigEmpty.class);
|
||||
assertFalse(ctx.getBeanFactory().containsSingleton("l0ConfigEmpty"));
|
||||
Object l0i1 = ctx.getBean(L0ConfigEmpty.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
|
||||
@Lazy
|
||||
static class L0Config {
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public TestBean l0Bean() {
|
||||
return new TestBean("l0");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public TestBean overrideBean() {
|
||||
return new TestBean("override-l0");
|
||||
}
|
||||
|
|
@ -148,14 +232,17 @@ public class NestedConfigurationClassTests {
|
|||
}
|
||||
|
||||
@Configuration
|
||||
@Lazy
|
||||
protected static class L2Config {
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public TestBean l2Bean() {
|
||||
return new TestBean("l2");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public TestBean overrideBean() {
|
||||
return new TestBean("override-l2");
|
||||
}
|
||||
|
|
@ -165,14 +252,17 @@ public class NestedConfigurationClassTests {
|
|||
|
||||
|
||||
@Component
|
||||
@Lazy
|
||||
static class L0ConfigLight {
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public TestBean l0Bean() {
|
||||
return new TestBean("l0");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public TestBean overrideBean() {
|
||||
return new TestBean("override-l0");
|
||||
}
|
||||
|
|
@ -191,14 +281,17 @@ public class NestedConfigurationClassTests {
|
|||
}
|
||||
|
||||
@Component
|
||||
@Lazy
|
||||
protected static class L2ConfigLight {
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public TestBean l2Bean() {
|
||||
return new TestBean("l2");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
public TestBean overrideBean() {
|
||||
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
|
||||
@Scope("prototype")
|
||||
static class S1Config extends L0Config {
|
||||
|
||||
@Override
|
||||
|
|
@ -228,6 +309,60 @@ public class NestedConfigurationClassTests {
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@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