Skip to content

Commit a7ec6dc

Browse files
committed
ImportRegistry properly tracks excluded superclasses
Issue: SPR-14972
1 parent e1b89c7 commit a7ec6dc

File tree

5 files changed

+81
-21
lines changed

5 files changed

+81
-21
lines changed

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassBeanDefinitionReader.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configC
129129
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
130130
this.registry.removeBeanDefinition(beanName);
131131
}
132-
this.importRegistry.removeImportingClassFor(configClass.getMetadata().getClassName());
132+
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
133133
return;
134134
}
135135

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -644,22 +644,23 @@ public void registerImport(AnnotationMetadata importingClass, String importedCla
644644
}
645645

646646
@Override
647-
public void removeImportingClassFor(String importedClass) {
647+
public AnnotationMetadata getImportingClassFor(String importedClass) {
648+
List<AnnotationMetadata> list = this.imports.get(importedClass);
649+
return (!CollectionUtils.isEmpty(list) ? list.get(list.size() - 1) : null);
650+
}
651+
652+
@Override
653+
public void removeImportingClass(String importingClass) {
648654
for (List<AnnotationMetadata> list : this.imports.values()) {
649655
for (Iterator<AnnotationMetadata> iterator = list.iterator(); iterator.hasNext();) {
650-
if (iterator.next().getClassName().equals(importedClass)) {
656+
if (iterator.next().getClassName().equals(importingClass)) {
651657
iterator.remove();
658+
break;
652659
}
653660
}
654661
}
655662
}
656663

657-
@Override
658-
public AnnotationMetadata getImportingClassFor(String importedClass) {
659-
List<AnnotationMetadata> list = this.imports.get(importedClass);
660-
return (!CollectionUtils.isEmpty(list) ? list.get(list.size() - 1) : null);
661-
}
662-
663664
/**
664665
* Given a stack containing (in order)
665666
* <ul>

spring-context/src/main/java/org/springframework/context/annotation/ConfigurationCondition.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ public interface ConfigurationCondition extends Condition {
3838
/**
3939
* The various configuration phases where the condition could be evaluated.
4040
*/
41-
public static enum ConfigurationPhase {
41+
enum ConfigurationPhase {
4242

4343
/**
4444
* The {@link Condition} should be evaluated as a {@code @Configuration}

spring-context/src/main/java/org/springframework/context/annotation/ImportRegistry.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,6 +26,6 @@ interface ImportRegistry {
2626

2727
AnnotationMetadata getImportingClassFor(String importedClass);
2828

29-
void removeImportingClassFor(String importedClass);
29+
void removeImportingClass(String importingClass);
3030

3131
}

spring-tx/src/test/java/org/springframework/transaction/annotation/EnableTransactionManagementTests.java

+67-8
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@
2626
import org.springframework.context.annotation.AdviceMode;
2727
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
2828
import org.springframework.context.annotation.Bean;
29+
import org.springframework.context.annotation.ConditionContext;
30+
import org.springframework.context.annotation.Conditional;
2931
import org.springframework.context.annotation.Configuration;
32+
import org.springframework.context.annotation.ConfigurationCondition;
33+
import org.springframework.core.type.AnnotatedTypeMetadata;
3034
import org.springframework.stereotype.Service;
3135
import org.springframework.tests.transaction.CallCountingTransactionManager;
3236
import org.springframework.transaction.PlatformTransactionManager;
@@ -49,7 +53,8 @@ public class EnableTransactionManagementTests {
4953

5054
@Test
5155
public void transactionProxyIsCreated() {
52-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(EnableTxConfig.class, TxManagerConfig.class);
56+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
57+
EnableTxConfig.class, TxManagerConfig.class);
5358
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
5459
assertTrue("testBean is not a proxy", AopUtils.isAopProxy(bean));
5560
Map<?,?> services = ctx.getBeansWithAnnotation(Service.class);
@@ -59,7 +64,19 @@ public void transactionProxyIsCreated() {
5964

6065
@Test
6166
public void transactionProxyIsCreatedWithEnableOnSuperclass() {
62-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(InheritedEnableTxConfig.class, TxManagerConfig.class);
67+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
68+
InheritedEnableTxConfig.class, TxManagerConfig.class);
69+
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
70+
assertTrue("testBean is not a proxy", AopUtils.isAopProxy(bean));
71+
Map<?,?> services = ctx.getBeansWithAnnotation(Service.class);
72+
assertTrue("Stereotype annotation not visible", services.containsKey("testBean"));
73+
ctx.close();
74+
}
75+
76+
@Test
77+
public void transactionProxyIsCreatedWithEnableOnExcludedSuperclass() {
78+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
79+
ParentEnableTxConfig.class, ChildEnableTxConfig.class, TxManagerConfig.class);
6380
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
6481
assertTrue("testBean is not a proxy", AopUtils.isAopProxy(bean));
6582
Map<?,?> services = ctx.getBeansWithAnnotation(Service.class);
@@ -69,7 +86,8 @@ public void transactionProxyIsCreatedWithEnableOnSuperclass() {
6986

7087
@Test
7188
public void txManagerIsResolvedOnInvocationOfTransactionalMethod() {
72-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(EnableTxConfig.class, TxManagerConfig.class);
89+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
90+
EnableTxConfig.class, TxManagerConfig.class);
7391
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
7492

7593
// invoke a transactional method, causing the PlatformTransactionManager bean to be resolved.
@@ -79,7 +97,8 @@ public void txManagerIsResolvedOnInvocationOfTransactionalMethod() {
7997

8098
@Test
8199
public void txManagerIsResolvedCorrectlyWhenMultipleManagersArePresent() {
82-
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(EnableTxConfig.class, MultiTxManagerConfig.class);
100+
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
101+
EnableTxConfig.class, MultiTxManagerConfig.class);
83102
TransactionalTestBean bean = ctx.getBean(TransactionalTestBean.class);
84103

85104
// invoke a transactional method, causing the PlatformTransactionManager bean to be resolved.
@@ -95,7 +114,7 @@ public void txManagerIsResolvedCorrectlyWhenMultipleManagersArePresent() {
95114
@SuppressWarnings("resource")
96115
public void proxyTypeAspectJCausesRegistrationOfAnnotationTransactionAspect() {
97116
try {
98-
new AnnotationConfigApplicationContext(EnableAspectJTxConfig.class, TxManagerConfig.class);
117+
new AnnotationConfigApplicationContext(EnableAspectjTxConfig.class, TxManagerConfig.class);
99118
fail("should have thrown CNFE when trying to load AnnotationTransactionAspect. " +
100119
"Do you actually have org.springframework.aspects on the classpath?");
101120
}
@@ -137,15 +156,54 @@ public void spr11915() {
137156
static class EnableTxConfig {
138157
}
139158

159+
140160
@Configuration
141161
static class InheritedEnableTxConfig extends EnableTxConfig {
142162
}
143163

164+
165+
@Configuration
166+
@EnableTransactionManagement
167+
@Conditional(NeverCondition.class)
168+
static class ParentEnableTxConfig {
169+
170+
@Bean
171+
Object someBean() {
172+
return new Object();
173+
}
174+
}
175+
176+
177+
@Configuration
178+
static class ChildEnableTxConfig extends ParentEnableTxConfig {
179+
180+
@Override
181+
Object someBean() {
182+
return "X";
183+
}
184+
}
185+
186+
187+
private static class NeverCondition implements ConfigurationCondition {
188+
189+
@Override
190+
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
191+
return false;
192+
}
193+
194+
@Override
195+
public ConfigurationPhase getConfigurationPhase() {
196+
return ConfigurationPhase.REGISTER_BEAN;
197+
}
198+
}
199+
200+
144201
@Configuration
145-
@EnableTransactionManagement(mode=AdviceMode.ASPECTJ)
146-
static class EnableAspectJTxConfig {
202+
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
203+
static class EnableAspectjTxConfig {
147204
}
148205

206+
149207
@Configuration
150208
@EnableTransactionManagement
151209
static class Spr11915Config {
@@ -162,6 +220,7 @@ public TransactionalTestBean testBean() {
162220
}
163221
}
164222

223+
165224
@Configuration
166225
static class TxManagerConfig {
167226

@@ -174,9 +233,9 @@ public TransactionalTestBean testBean() {
174233
public PlatformTransactionManager txManager() {
175234
return new CallCountingTransactionManager();
176235
}
177-
178236
}
179237

238+
180239
@Configuration
181240
static class MultiTxManagerConfig extends TxManagerConfig implements TransactionManagementConfigurer {
182241

0 commit comments

Comments
 (0)