|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2021 the original author or authors. |
| 2 | + * Copyright 2002-2022 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
22 | 22 | import java.util.HashSet;
|
23 | 23 | import java.util.List;
|
24 | 24 | import java.util.Set;
|
| 25 | +import java.util.function.BiConsumer; |
25 | 26 |
|
26 | 27 | import org.apache.commons.logging.Log;
|
27 | 28 | import org.apache.commons.logging.LogFactory;
|
28 | 29 |
|
| 30 | +import org.springframework.beans.PropertyValue; |
29 | 31 | import org.springframework.beans.factory.config.BeanDefinition;
|
30 | 32 | import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
31 | 33 | import org.springframework.beans.factory.config.BeanPostProcessor;
|
32 | 34 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
| 35 | +import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; |
| 36 | +import org.springframework.beans.factory.support.AbstractBeanDefinition; |
33 | 37 | import org.springframework.beans.factory.support.AbstractBeanFactory;
|
34 | 38 | import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
35 | 39 | import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
|
| 40 | +import org.springframework.beans.factory.support.BeanDefinitionValueResolver; |
36 | 41 | import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
37 | 42 | import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
|
| 43 | +import org.springframework.beans.factory.support.RootBeanDefinition; |
38 | 44 | import org.springframework.core.OrderComparator;
|
39 | 45 | import org.springframework.core.Ordered;
|
40 | 46 | import org.springframework.core.PriorityOrdered;
|
|
47 | 53 | *
|
48 | 54 | * @author Juergen Hoeller
|
49 | 55 | * @author Sam Brannen
|
| 56 | + * @author Stephane Nicoll |
50 | 57 | * @since 4.0
|
51 | 58 | */
|
52 | 59 | final class PostProcessorRegistrationDelegate {
|
@@ -280,6 +287,36 @@ else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
|
280 | 287 | beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
|
281 | 288 | }
|
282 | 289 |
|
| 290 | + /** |
| 291 | + * Load and sort the post-processors of the specified type. |
| 292 | + * @param beanFactory the bean factory to use |
| 293 | + * @param beanPostProcessorType the post-processor type |
| 294 | + * @param <T> the post-processor type |
| 295 | + * @return a list of sorted post-processors for the specified type |
| 296 | + */ |
| 297 | + static <T extends BeanPostProcessor> List<T> loadBeanPostProcessors( |
| 298 | + ConfigurableListableBeanFactory beanFactory, Class<T> beanPostProcessorType) { |
| 299 | + |
| 300 | + String[] postProcessorNames = beanFactory.getBeanNamesForType(beanPostProcessorType, true, false); |
| 301 | + List<T> postProcessors = new ArrayList<>(); |
| 302 | + for (String ppName : postProcessorNames) { |
| 303 | + postProcessors.add(beanFactory.getBean(ppName, beanPostProcessorType)); |
| 304 | + } |
| 305 | + sortPostProcessors(postProcessors, beanFactory); |
| 306 | + return postProcessors; |
| 307 | + |
| 308 | + } |
| 309 | + |
| 310 | + /** |
| 311 | + * Selectively invoke {@link MergedBeanDefinitionPostProcessor} instances |
| 312 | + * registered in the specified bean factory, resolving bean definitions as |
| 313 | + * well as any inner bean definitions that they may contain. |
| 314 | + * @param beanFactory the bean factory to use |
| 315 | + */ |
| 316 | + static void invokeMergedBeanDefinitionPostProcessors(DefaultListableBeanFactory beanFactory) { |
| 317 | + new MergedBeanDefinitionPostProcessorInvoker(beanFactory).invokeMergedBeanDefinitionPostProcessors(); |
| 318 | + } |
| 319 | + |
283 | 320 | private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
|
284 | 321 | // Nothing to sort?
|
285 | 322 | if (postProcessors.size() <= 1) {
|
@@ -386,4 +423,65 @@ private boolean isInfrastructureBean(@Nullable String beanName) {
|
386 | 423 | }
|
387 | 424 | }
|
388 | 425 |
|
| 426 | + private static final class MergedBeanDefinitionPostProcessorInvoker { |
| 427 | + |
| 428 | + private final DefaultListableBeanFactory beanFactory; |
| 429 | + |
| 430 | + private MergedBeanDefinitionPostProcessorInvoker(DefaultListableBeanFactory beanFactory) { |
| 431 | + this.beanFactory = beanFactory; |
| 432 | + } |
| 433 | + |
| 434 | + private void invokeMergedBeanDefinitionPostProcessors() { |
| 435 | + List<MergedBeanDefinitionPostProcessor> postProcessors = PostProcessorRegistrationDelegate.loadBeanPostProcessors( |
| 436 | + this.beanFactory, MergedBeanDefinitionPostProcessor.class); |
| 437 | + for (String beanName : this.beanFactory.getBeanDefinitionNames()) { |
| 438 | + RootBeanDefinition bd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName); |
| 439 | + Class<?> beanType = resolveBeanType(bd); |
| 440 | + postProcessRootBeanDefinition(postProcessors, beanName, beanType, bd); |
| 441 | + } |
| 442 | + } |
| 443 | + |
| 444 | + private void postProcessRootBeanDefinition(List<MergedBeanDefinitionPostProcessor> postProcessors, |
| 445 | + String beanName, Class<?> beanType, RootBeanDefinition bd) { |
| 446 | + BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this.beanFactory, beanName, bd); |
| 447 | + postProcessors.forEach(postProcessor -> postProcessor.postProcessMergedBeanDefinition(bd, beanType, beanName)); |
| 448 | + for (PropertyValue propertyValue : bd.getPropertyValues().getPropertyValueList()) { |
| 449 | + Object value = propertyValue.getValue(); |
| 450 | + if (value instanceof AbstractBeanDefinition innerBd) { |
| 451 | + Class<?> innerBeanType = resolveBeanType(innerBd); |
| 452 | + resolveInnerBeanDefinition(valueResolver, innerBd, (innerBeanName, innerBeanDefinition) |
| 453 | + -> postProcessRootBeanDefinition(postProcessors, innerBeanName, innerBeanType, innerBeanDefinition)); |
| 454 | + } |
| 455 | + } |
| 456 | + for (ValueHolder valueHolder : bd.getConstructorArgumentValues().getIndexedArgumentValues().values()) { |
| 457 | + Object value = valueHolder.getValue(); |
| 458 | + if (value instanceof AbstractBeanDefinition innerBd) { |
| 459 | + Class<?> innerBeanType = resolveBeanType(innerBd); |
| 460 | + resolveInnerBeanDefinition(valueResolver, innerBd, (innerBeanName, innerBeanDefinition) |
| 461 | + -> postProcessRootBeanDefinition(postProcessors, innerBeanName, innerBeanType, innerBeanDefinition)); |
| 462 | + } |
| 463 | + } |
| 464 | + } |
| 465 | + |
| 466 | + private void resolveInnerBeanDefinition(BeanDefinitionValueResolver valueResolver, BeanDefinition innerBeanDefinition, |
| 467 | + BiConsumer<String, RootBeanDefinition> resolver) { |
| 468 | + valueResolver.resolveInnerBean(null, innerBeanDefinition, (name, rbd) -> { |
| 469 | + resolver.accept(name, rbd); |
| 470 | + return Void.class; |
| 471 | + }); |
| 472 | + } |
| 473 | + |
| 474 | + private Class<?> resolveBeanType(AbstractBeanDefinition bd) { |
| 475 | + if (!bd.hasBeanClass()) { |
| 476 | + try { |
| 477 | + bd.resolveBeanClass(this.beanFactory.getBeanClassLoader()); |
| 478 | + } |
| 479 | + catch (ClassNotFoundException ex) { |
| 480 | + // ignore |
| 481 | + } |
| 482 | + } |
| 483 | + return bd.getResolvableType().toClass(); |
| 484 | + } |
| 485 | + } |
| 486 | + |
389 | 487 | }
|
0 commit comments