diff --git a/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java b/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java index 9e347ba5dd2..138e798ae5e 100644 --- a/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java +++ b/spring-context/src/main/java/org/springframework/context/support/PostProcessorRegistrationDelegate.java @@ -58,15 +58,14 @@ class PostProcessorRegistrationDelegate { if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List regularPostProcessors = new LinkedList(); - List registryPostProcessors = - new LinkedList(); + List registryProcessors = new LinkedList(); for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { - BeanDefinitionRegistryPostProcessor registryPostProcessor = + BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; - registryPostProcessor.postProcessBeanDefinitionRegistry(registry); - registryPostProcessors.add(registryPostProcessor); + registryProcessor.postProcessBeanDefinitionRegistry(registry); + registryProcessors.add(registryProcessor); } else { regularPostProcessors.add(postProcessor); @@ -77,33 +76,34 @@ class PostProcessorRegistrationDelegate { // uninitialized to let the bean factory post-processors apply to them! // Separate between BeanDefinitionRegistryPostProcessors that implement // PriorityOrdered, Ordered, and the rest. - String[] postProcessorNames = - beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); + List currentRegistryProcessors = new ArrayList(); // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered. - List priorityOrderedPostProcessors = new ArrayList(); + String[] postProcessorNames = + beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { - priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); + currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } - sortPostProcessors(beanFactory, priorityOrderedPostProcessors); - registryPostProcessors.addAll(priorityOrderedPostProcessors); - invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry); + sortPostProcessors(currentRegistryProcessors, beanFactory); + registryProcessors.addAll(currentRegistryProcessors); + invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); + currentRegistryProcessors.clear(); // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered. postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); - List orderedPostProcessors = new ArrayList(); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { - orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); + currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } - sortPostProcessors(beanFactory, orderedPostProcessors); - registryPostProcessors.addAll(orderedPostProcessors); - invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry); + sortPostProcessors(currentRegistryProcessors, beanFactory); + registryProcessors.addAll(currentRegistryProcessors); + invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); + currentRegistryProcessors.clear(); // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear. boolean reiterate = true; @@ -112,17 +112,19 @@ class PostProcessorRegistrationDelegate { postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { - BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class); - registryPostProcessors.add(pp); + currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); - pp.postProcessBeanDefinitionRegistry(registry); reiterate = true; } } + sortPostProcessors(currentRegistryProcessors, beanFactory); + registryProcessors.addAll(currentRegistryProcessors); + invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); + currentRegistryProcessors.clear(); } // Now, invoke the postProcessBeanFactory callback of all processors handled so far. - invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory); + invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } @@ -157,7 +159,7 @@ class PostProcessorRegistrationDelegate { } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. - sortPostProcessors(beanFactory, priorityOrderedPostProcessors); + sortPostProcessors(priorityOrderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. @@ -165,7 +167,7 @@ class PostProcessorRegistrationDelegate { for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } - sortPostProcessors(beanFactory, orderedPostProcessors); + sortPostProcessors(orderedPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. @@ -214,7 +216,7 @@ class PostProcessorRegistrationDelegate { } // First, register the BeanPostProcessors that implement PriorityOrdered. - sortPostProcessors(beanFactory, priorityOrderedPostProcessors); + sortPostProcessors(priorityOrderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement Ordered. @@ -226,7 +228,7 @@ class PostProcessorRegistrationDelegate { internalPostProcessors.add(pp); } } - sortPostProcessors(beanFactory, orderedPostProcessors); + sortPostProcessors(orderedPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // Now, register all regular BeanPostProcessors. @@ -241,7 +243,7 @@ class PostProcessorRegistrationDelegate { registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // Finally, re-register all internal BeanPostProcessors. - sortPostProcessors(beanFactory, internalPostProcessors); + sortPostProcessors(internalPostProcessors, beanFactory); registerBeanPostProcessors(beanFactory, internalPostProcessors); // Re-register post-processor for detecting inner beans as ApplicationListeners, @@ -249,7 +251,7 @@ class PostProcessorRegistrationDelegate { beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); } - private static void sortPostProcessors(ConfigurableListableBeanFactory beanFactory, List postProcessors) { + private static void sortPostProcessors(List postProcessors, ConfigurableListableBeanFactory beanFactory) { Comparator comparatorToUse = null; if (beanFactory instanceof DefaultListableBeanFactory) { comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator(); diff --git a/spring-context/src/test/java/org/springframework/context/support/BeanFactoryPostProcessorTests.java b/spring-context/src/test/java/org/springframework/context/support/BeanFactoryPostProcessorTests.java index 1c9d437f03b..2b053a581b9 100644 --- a/spring-context/src/test/java/org/springframework/context/support/BeanFactoryPostProcessorTests.java +++ b/spring-context/src/test/java/org/springframework/context/support/BeanFactoryPostProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.core.Ordered; import org.springframework.core.PriorityOrdered; import org.springframework.tests.sample.beans.TestBean; import org.springframework.util.Assert; @@ -101,26 +102,40 @@ public class BeanFactoryPostProcessorTests { } @Test - public void testBeanDefinitionRegistryPostProcessor() throws Exception { + public void testBeanDefinitionRegistryPostProcessor() { StaticApplicationContext ac = new StaticApplicationContext(); ac.registerSingleton("tb1", TestBean.class); ac.registerSingleton("tb2", TestBean.class); + ac.addBeanFactoryPostProcessor(new PrioritizedBeanDefinitionRegistryPostProcessor()); TestBeanDefinitionRegistryPostProcessor bdrpp = new TestBeanDefinitionRegistryPostProcessor(); ac.addBeanFactoryPostProcessor(bdrpp); assertFalse(bdrpp.wasCalled); ac.refresh(); assertTrue(bdrpp.wasCalled); - assertTrue(ac.getBean(TestBeanFactoryPostProcessor.class).wasCalled); + assertTrue(ac.getBean("bfpp1", TestBeanFactoryPostProcessor.class).wasCalled); + assertTrue(ac.getBean("bfpp2", TestBeanFactoryPostProcessor.class).wasCalled); } @Test - public void testBeanDefinitionRegistryPostProcessorRegisteringAnother() throws Exception { + public void testBeanDefinitionRegistryPostProcessorRegisteringAnother() { StaticApplicationContext ac = new StaticApplicationContext(); ac.registerSingleton("tb1", TestBean.class); ac.registerSingleton("tb2", TestBean.class); - ac.registerBeanDefinition("bdrpp2", new RootBeanDefinition(TestBeanDefinitionRegistryPostProcessor2.class)); + ac.registerBeanDefinition("bdrpp2", new RootBeanDefinition(OuterBeanDefinitionRegistryPostProcessor.class)); ac.refresh(); - assertTrue(ac.getBean(TestBeanFactoryPostProcessor.class).wasCalled); + assertTrue(ac.getBean("bfpp1", TestBeanFactoryPostProcessor.class).wasCalled); + assertTrue(ac.getBean("bfpp2", TestBeanFactoryPostProcessor.class).wasCalled); + } + + @Test + public void testPrioritizedBeanDefinitionRegistryPostProcessorRegisteringAnother() { + StaticApplicationContext ac = new StaticApplicationContext(); + ac.registerSingleton("tb1", TestBean.class); + ac.registerSingleton("tb2", TestBean.class); + ac.registerBeanDefinition("bdrpp2", new RootBeanDefinition(PrioritizedOuterBeanDefinitionRegistryPostProcessor.class)); + ac.refresh(); + assertTrue(ac.getBean("bfpp1", TestBeanFactoryPostProcessor.class).wasCalled); + assertTrue(ac.getBean("bfpp2", TestBeanFactoryPostProcessor.class).wasCalled); } @Test @@ -159,13 +174,32 @@ public class BeanFactoryPostProcessorTests { } + public static class PrioritizedBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered { + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + registry.registerBeanDefinition("bfpp1", new RootBeanDefinition(TestBeanFactoryPostProcessor.class)); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + } + } + + public static class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { public boolean wasCalled; @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - registry.registerBeanDefinition("bfpp", new RootBeanDefinition(TestBeanFactoryPostProcessor.class)); + assertTrue(registry.containsBeanDefinition("bfpp1")); + registry.registerBeanDefinition("bfpp2", new RootBeanDefinition(TestBeanFactoryPostProcessor.class)); } @Override @@ -175,16 +209,22 @@ public class BeanFactoryPostProcessorTests { } - public static class TestBeanDefinitionRegistryPostProcessor2 implements BeanDefinitionRegistryPostProcessor, PriorityOrdered { + public static class OuterBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { registry.registerBeanDefinition("anotherpp", new RootBeanDefinition(TestBeanDefinitionRegistryPostProcessor.class)); + registry.registerBeanDefinition("ppp", new RootBeanDefinition(PrioritizedBeanDefinitionRegistryPostProcessor.class)); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { } + } + + + public static class PrioritizedOuterBeanDefinitionRegistryPostProcessor extends OuterBeanDefinitionRegistryPostProcessor + implements PriorityOrdered { @Override public int getOrder() {