Skip to content

Commit ad4c8e7

Browse files
committed
Consistently sort BeanDefinitionRegistryPostProcessors
Issue: SPR-16043
1 parent 53091c7 commit ad4c8e7

File tree

2 files changed

+77
-35
lines changed

2 files changed

+77
-35
lines changed

spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java

+29-27
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,14 @@ public static void invokeBeanFactoryPostProcessors(
5959
if (beanFactory instanceof BeanDefinitionRegistry) {
6060
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
6161
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
62-
List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
63-
new LinkedList<>();
62+
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
6463

6564
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
6665
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
67-
BeanDefinitionRegistryPostProcessor registryPostProcessor =
66+
BeanDefinitionRegistryPostProcessor registryProcessor =
6867
(BeanDefinitionRegistryPostProcessor) postProcessor;
69-
registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
70-
registryPostProcessors.add(registryPostProcessor);
68+
registryProcessor.postProcessBeanDefinitionRegistry(registry);
69+
registryProcessors.add(registryProcessor);
7170
}
7271
else {
7372
regularPostProcessors.add(postProcessor);
@@ -78,33 +77,34 @@ public static void invokeBeanFactoryPostProcessors(
7877
// uninitialized to let the bean factory post-processors apply to them!
7978
// Separate between BeanDefinitionRegistryPostProcessors that implement
8079
// PriorityOrdered, Ordered, and the rest.
81-
String[] postProcessorNames =
82-
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
80+
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
8381

8482
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
85-
List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
83+
String[] postProcessorNames =
84+
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
8685
for (String ppName : postProcessorNames) {
8786
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
88-
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
87+
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
8988
processedBeans.add(ppName);
9089
}
9190
}
92-
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
93-
registryPostProcessors.addAll(priorityOrderedPostProcessors);
94-
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
91+
sortPostProcessors(currentRegistryProcessors, beanFactory);
92+
registryProcessors.addAll(currentRegistryProcessors);
93+
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
94+
currentRegistryProcessors.clear();
9595

9696
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
9797
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
98-
List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<>();
9998
for (String ppName : postProcessorNames) {
10099
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
101-
orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
100+
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
102101
processedBeans.add(ppName);
103102
}
104103
}
105-
sortPostProcessors(beanFactory, orderedPostProcessors);
106-
registryPostProcessors.addAll(orderedPostProcessors);
107-
invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
104+
sortPostProcessors(currentRegistryProcessors, beanFactory);
105+
registryProcessors.addAll(currentRegistryProcessors);
106+
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
107+
currentRegistryProcessors.clear();
108108

109109
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
110110
boolean reiterate = true;
@@ -113,17 +113,19 @@ public static void invokeBeanFactoryPostProcessors(
113113
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
114114
for (String ppName : postProcessorNames) {
115115
if (!processedBeans.contains(ppName)) {
116-
BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
117-
registryPostProcessors.add(pp);
116+
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
118117
processedBeans.add(ppName);
119-
pp.postProcessBeanDefinitionRegistry(registry);
120118
reiterate = true;
121119
}
122120
}
121+
sortPostProcessors(currentRegistryProcessors, beanFactory);
122+
registryProcessors.addAll(currentRegistryProcessors);
123+
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
124+
currentRegistryProcessors.clear();
123125
}
124126

125127
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
126-
invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
128+
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
127129
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
128130
}
129131

@@ -158,15 +160,15 @@ else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
158160
}
159161

160162
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
161-
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
163+
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
162164
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
163165

164166
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
165167
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
166168
for (String postProcessorName : orderedPostProcessorNames) {
167169
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
168170
}
169-
sortPostProcessors(beanFactory, orderedPostProcessors);
171+
sortPostProcessors(orderedPostProcessors, beanFactory);
170172
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
171173

172174
// Finally, invoke all other BeanFactoryPostProcessors.
@@ -215,7 +217,7 @@ else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
215217
}
216218

217219
// First, register the BeanPostProcessors that implement PriorityOrdered.
218-
sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
220+
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
219221
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
220222

221223
// Next, register the BeanPostProcessors that implement Ordered.
@@ -227,7 +229,7 @@ else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
227229
internalPostProcessors.add(pp);
228230
}
229231
}
230-
sortPostProcessors(beanFactory, orderedPostProcessors);
232+
sortPostProcessors(orderedPostProcessors, beanFactory);
231233
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
232234

233235
// Now, register all regular BeanPostProcessors.
@@ -242,15 +244,15 @@ else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
242244
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
243245

244246
// Finally, re-register all internal BeanPostProcessors.
245-
sortPostProcessors(beanFactory, internalPostProcessors);
247+
sortPostProcessors(internalPostProcessors, beanFactory);
246248
registerBeanPostProcessors(beanFactory, internalPostProcessors);
247249

248250
// Re-register post-processor for detecting inner beans as ApplicationListeners,
249251
// moving it to the end of the processor chain (for picking up proxies etc).
250252
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
251253
}
252254

253-
private static void sortPostProcessors(ConfigurableListableBeanFactory beanFactory, List<?> postProcessors) {
255+
private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
254256
Comparator<Object> comparatorToUse = null;
255257
if (beanFactory instanceof DefaultListableBeanFactory) {
256258
comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();

spring-context/src/test/java/org/springframework/context/support/BeanFactoryPostProcessorTests.java

+48-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 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.
@@ -31,6 +31,7 @@
3131
import org.springframework.context.ApplicationEvent;
3232
import org.springframework.context.ApplicationListener;
3333
import org.springframework.context.event.ContextRefreshedEvent;
34+
import org.springframework.core.Ordered;
3435
import org.springframework.core.PriorityOrdered;
3536
import org.springframework.tests.sample.beans.TestBean;
3637
import org.springframework.util.Assert;
@@ -101,26 +102,40 @@ public void testBeanFactoryPostProcessorNotExecutedByBeanFactory() {
101102
}
102103

103104
@Test
104-
public void testBeanDefinitionRegistryPostProcessor() throws Exception {
105+
public void testBeanDefinitionRegistryPostProcessor() {
105106
StaticApplicationContext ac = new StaticApplicationContext();
106107
ac.registerSingleton("tb1", TestBean.class);
107108
ac.registerSingleton("tb2", TestBean.class);
109+
ac.addBeanFactoryPostProcessor(new PrioritizedBeanDefinitionRegistryPostProcessor());
108110
TestBeanDefinitionRegistryPostProcessor bdrpp = new TestBeanDefinitionRegistryPostProcessor();
109111
ac.addBeanFactoryPostProcessor(bdrpp);
110112
assertFalse(bdrpp.wasCalled);
111113
ac.refresh();
112114
assertTrue(bdrpp.wasCalled);
113-
assertTrue(ac.getBean(TestBeanFactoryPostProcessor.class).wasCalled);
115+
assertTrue(ac.getBean("bfpp1", TestBeanFactoryPostProcessor.class).wasCalled);
116+
assertTrue(ac.getBean("bfpp2", TestBeanFactoryPostProcessor.class).wasCalled);
114117
}
115118

116119
@Test
117-
public void testBeanDefinitionRegistryPostProcessorRegisteringAnother() throws Exception {
120+
public void testBeanDefinitionRegistryPostProcessorRegisteringAnother() {
118121
StaticApplicationContext ac = new StaticApplicationContext();
119122
ac.registerSingleton("tb1", TestBean.class);
120123
ac.registerSingleton("tb2", TestBean.class);
121-
ac.registerBeanDefinition("bdrpp2", new RootBeanDefinition(TestBeanDefinitionRegistryPostProcessor2.class));
124+
ac.registerBeanDefinition("bdrpp2", new RootBeanDefinition(OuterBeanDefinitionRegistryPostProcessor.class));
122125
ac.refresh();
123-
assertTrue(ac.getBean(TestBeanFactoryPostProcessor.class).wasCalled);
126+
assertTrue(ac.getBean("bfpp1", TestBeanFactoryPostProcessor.class).wasCalled);
127+
assertTrue(ac.getBean("bfpp2", TestBeanFactoryPostProcessor.class).wasCalled);
128+
}
129+
130+
@Test
131+
public void testPrioritizedBeanDefinitionRegistryPostProcessorRegisteringAnother() {
132+
StaticApplicationContext ac = new StaticApplicationContext();
133+
ac.registerSingleton("tb1", TestBean.class);
134+
ac.registerSingleton("tb2", TestBean.class);
135+
ac.registerBeanDefinition("bdrpp2", new RootBeanDefinition(PrioritizedOuterBeanDefinitionRegistryPostProcessor.class));
136+
ac.refresh();
137+
assertTrue(ac.getBean("bfpp1", TestBeanFactoryPostProcessor.class).wasCalled);
138+
assertTrue(ac.getBean("bfpp2", TestBeanFactoryPostProcessor.class).wasCalled);
124139
}
125140

126141
@Test
@@ -159,13 +174,32 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
159174
}
160175

161176

177+
public static class PrioritizedBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {
178+
179+
@Override
180+
public int getOrder() {
181+
return Ordered.HIGHEST_PRECEDENCE;
182+
}
183+
184+
@Override
185+
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
186+
registry.registerBeanDefinition("bfpp1", new RootBeanDefinition(TestBeanFactoryPostProcessor.class));
187+
}
188+
189+
@Override
190+
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
191+
}
192+
}
193+
194+
162195
public static class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
163196

164197
public boolean wasCalled;
165198

166199
@Override
167200
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
168-
registry.registerBeanDefinition("bfpp", new RootBeanDefinition(TestBeanFactoryPostProcessor.class));
201+
assertTrue(registry.containsBeanDefinition("bfpp1"));
202+
registry.registerBeanDefinition("bfpp2", new RootBeanDefinition(TestBeanFactoryPostProcessor.class));
169203
}
170204

171205
@Override
@@ -175,16 +209,22 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
175209
}
176210

177211

178-
public static class TestBeanDefinitionRegistryPostProcessor2 implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
212+
public static class OuterBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
179213

180214
@Override
181215
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
182216
registry.registerBeanDefinition("anotherpp", new RootBeanDefinition(TestBeanDefinitionRegistryPostProcessor.class));
217+
registry.registerBeanDefinition("ppp", new RootBeanDefinition(PrioritizedBeanDefinitionRegistryPostProcessor.class));
183218
}
184219

185220
@Override
186221
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
187222
}
223+
}
224+
225+
226+
public static class PrioritizedOuterBeanDefinitionRegistryPostProcessor extends OuterBeanDefinitionRegistryPostProcessor
227+
implements PriorityOrdered {
188228

189229
@Override
190230
public int getOrder() {

0 commit comments

Comments
 (0)