• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TAKETODAY / today-infrastructure / 18154768944

01 Oct 2025 07:26AM UTC coverage: 81.882% (-0.005%) from 81.887%
18154768944

push

github

web-flow
Merge pull request #290 from TAKETODAY/dev/jspecify

jspecify

59788 of 78013 branches covered (76.64%)

Branch coverage included in aggregate %.

141239 of 167496 relevant lines covered (84.32%)

3.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.88
today-context/src/main/java/infra/context/support/PostProcessorRegistrationDelegate.java
1
/*
2
 * Copyright 2017 - 2025 the original author or authors.
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see [https://www.gnu.org/licenses/]
16
 */
17

18
package infra.context.support;
19

20
import org.jspecify.annotations.Nullable;
21

22
import java.util.ArrayList;
23
import java.util.Collection;
24
import java.util.Comparator;
25
import java.util.HashSet;
26
import java.util.LinkedHashSet;
27
import java.util.List;
28
import java.util.Set;
29
import java.util.function.BiConsumer;
30

31
import infra.beans.PropertyValue;
32
import infra.beans.factory.InitializationBeanPostProcessor;
33
import infra.beans.factory.config.BeanDefinition;
34
import infra.beans.factory.config.BeanDefinitionHolder;
35
import infra.beans.factory.config.BeanFactoryPostProcessor;
36
import infra.beans.factory.config.BeanPostProcessor;
37
import infra.beans.factory.config.ConfigurableBeanFactory;
38
import infra.beans.factory.config.ConstructorArgumentValues.ValueHolder;
39
import infra.beans.factory.config.TypedStringValue;
40
import infra.beans.factory.support.AbstractBeanDefinition;
41
import infra.beans.factory.support.AbstractBeanFactory;
42
import infra.beans.factory.support.BeanDefinitionRegistry;
43
import infra.beans.factory.support.BeanDefinitionRegistryPostProcessor;
44
import infra.beans.factory.support.BeanDefinitionValueResolver;
45
import infra.beans.factory.support.MergedBeanDefinitionPostProcessor;
46
import infra.beans.factory.support.RootBeanDefinition;
47
import infra.beans.factory.support.StandardBeanFactory;
48
import infra.core.OrderComparator;
49
import infra.core.Ordered;
50
import infra.core.PriorityOrdered;
51
import infra.logging.Logger;
52
import infra.logging.LoggerFactory;
53

54
/**
55
 * Delegate for AbstractApplicationContext's post-processor handling.
56
 *
57
 * @author Juergen Hoeller
58
 * @author Sam Brannen
59
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
60
 * @since 4.0 2021/12/8 14:59
61
 */
62
final class PostProcessorRegistrationDelegate {
63

64
  private PostProcessorRegistrationDelegate() {
65
  }
66

67
  public static void invokeBeanFactoryPostProcessors(
68
          ConfigurableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
69

70
    // WARNING: Although it may appear that the body of this method can be easily
71
    // refactored to avoid the use of multiple loops and multiple lists, the use
72
    // of multiple lists and multiple passes over the names of processors is
73
    // intentional. We must ensure that we honor the contracts for PriorityOrdered
74
    // and Ordered processors. Specifically, we must NOT cause processors to be
75
    // instantiated (via getBean() invocations) or registered in the ApplicationContext
76
    // in the wrong order.
77

78
    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
79
    HashSet<String> processedBeans = new HashSet<>();
4✔
80

81
    if (beanFactory instanceof BeanDefinitionRegistry registry) {
6!
82
      ArrayList<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
4✔
83
      ArrayList<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
4✔
84

85
      for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
10✔
86
        if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {
6✔
87
          registryProcessor.postProcessBeanDefinitionRegistry(registry);
3✔
88
          registryProcessors.add(registryProcessor);
5✔
89
        }
90
        else {
91
          regularPostProcessors.add(postProcessor);
4✔
92
        }
93
      }
1✔
94

95
      // Do not initialize FactoryBeans here: We need to leave all regular beans
96
      // uninitialized to let the bean factory post-processors apply to them!
97
      // Separate between BeanDefinitionRegistryPostProcessors that implement
98
      // PriorityOrdered, Ordered, and the rest.
99
      ArrayList<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
4✔
100

101
      // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
102
      var postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
6✔
103
      for (String ppName : postProcessorNames) {
16✔
104
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
5✔
105
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
8✔
106
          processedBeans.add(ppName);
4✔
107
        }
108
      }
109
      sortPostProcessors(currentRegistryProcessors, beanFactory);
3✔
110
      registryProcessors.addAll(currentRegistryProcessors);
4✔
111
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
3✔
112
      currentRegistryProcessors.clear();
2✔
113

114
      // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
115
      postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
6✔
116
      for (String ppName : postProcessorNames) {
16✔
117
        if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
9✔
118
          currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
8✔
119
          processedBeans.add(ppName);
4✔
120
        }
121
      }
122
      sortPostProcessors(currentRegistryProcessors, beanFactory);
3✔
123
      registryProcessors.addAll(currentRegistryProcessors);
4✔
124
      invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
3✔
125
      currentRegistryProcessors.clear();
2✔
126

127
      // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
128
      boolean reiterate = true;
2✔
129
      while (reiterate) {
2✔
130
        reiterate = false;
2✔
131
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
6✔
132
        for (String ppName : postProcessorNames) {
16✔
133
          if (!processedBeans.contains(ppName)) {
4✔
134
            currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
8✔
135
            processedBeans.add(ppName);
4✔
136
            reiterate = true;
2✔
137
          }
138
        }
139
        sortPostProcessors(currentRegistryProcessors, beanFactory);
3✔
140
        registryProcessors.addAll(currentRegistryProcessors);
4✔
141
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
3✔
142
        currentRegistryProcessors.clear();
3✔
143
      }
144

145
      // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
146
      invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
3✔
147
      invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
3✔
148
    }
1✔
149

150
    else {
151
      // Invoke factory processors registered with the context instance.
152
      invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
×
153
    }
154

155
    // Do not initialize FactoryBeans here: We need to leave all regular beans
156
    // uninitialized to let the bean factory post-processors apply to them!
157
    var postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
6✔
158

159
    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
160
    // Ordered, and the rest.
161
    ArrayList<String> orderedPostProcessorNames = new ArrayList<>();
4✔
162
    ArrayList<String> nonOrderedPostProcessorNames = new ArrayList<>();
4✔
163
    ArrayList<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
4✔
164
    for (String ppName : postProcessorNames) {
16✔
165
      if (processedBeans.contains(ppName)) {
5✔
166
        // skip - already processed in first phase above
167
      }
168
      else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
5✔
169
        priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
9✔
170
      }
171
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
5✔
172
        orderedPostProcessorNames.add(ppName);
5✔
173
      }
174
      else {
175
        nonOrderedPostProcessorNames.add(ppName);
4✔
176
      }
177
    }
178

179
    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
180
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
3✔
181
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
3✔
182

183
    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
184
    ArrayList<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
6✔
185
    for (String postProcessorName : orderedPostProcessorNames) {
10✔
186
      orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
8✔
187
    }
1✔
188
    sortPostProcessors(orderedPostProcessors, beanFactory);
3✔
189
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
3✔
190

191
    // Finally, invoke all other BeanFactoryPostProcessors.
192
    ArrayList<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
6✔
193
    for (String postProcessorName : nonOrderedPostProcessorNames) {
10✔
194
      nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
8✔
195
    }
1✔
196
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
3✔
197

198
    // Clear cached merged bean definitions since the post-processors might have
199
    // modified the original metadata, e.g. replacing placeholders in values...
200
    beanFactory.clearMetadataCache();
2✔
201
  }
1✔
202

203
  public static void registerBeanPostProcessors(
204
          ConfigurableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
205

206
    // WARNING: Although it may appear that the body of this method can be easily
207
    // refactored to avoid the use of multiple loops and multiple lists, the use
208
    // of multiple lists and multiple passes over the names of processors is
209
    // intentional. We must ensure that we honor the contracts for PriorityOrdered
210
    // and Ordered processors. Specifically, we must NOT cause processors to be
211
    // instantiated (via getBean() invocations) or registered in the ApplicationContext
212
    // in the wrong order.
213

214
    var postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
6✔
215

216
    // Register BeanPostProcessorChecker that logs an info message when
217
    // a bean is created during BeanPostProcessor instantiation, i.e. when
218
    // a bean is not eligible for getting processed by all BeanPostProcessors.
219
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
8✔
220
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(
8✔
221
            beanFactory, postProcessorNames, beanProcessorTargetCount));
222

223
    // Separate between BeanPostProcessors that implement PriorityOrdered,
224
    // Ordered, and the rest.
225
    ArrayList<String> orderedPostProcessorNames = new ArrayList<>();
4✔
226
    ArrayList<String> nonOrderedPostProcessorNames = new ArrayList<>();
4✔
227
    ArrayList<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
4✔
228
    ArrayList<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
4✔
229
    for (String ppName : postProcessorNames) {
16✔
230
      if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
5✔
231
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
6✔
232
        priorityOrderedPostProcessors.add(pp);
4✔
233
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
3✔
234
          internalPostProcessors.add(pp);
4✔
235
        }
236
      }
1✔
237
      else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
5✔
238
        orderedPostProcessorNames.add(ppName);
5✔
239
      }
240
      else {
241
        nonOrderedPostProcessorNames.add(ppName);
4✔
242
      }
243
    }
244

245
    // First, register the BeanPostProcessors that implement PriorityOrdered.
246
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
3✔
247
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
3✔
248

249
    // Next, register the BeanPostProcessors that implement Ordered.
250
    ArrayList<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
6✔
251
    for (String ppName : orderedPostProcessorNames) {
10✔
252
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
6✔
253
      orderedPostProcessors.add(pp);
4✔
254
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
3✔
255
        internalPostProcessors.add(pp);
4✔
256
      }
257
    }
1✔
258
    sortPostProcessors(orderedPostProcessors, beanFactory);
3✔
259
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);
3✔
260

261
    // Now, register all regular BeanPostProcessors.
262
    ArrayList<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
6✔
263
    for (String ppName : nonOrderedPostProcessorNames) {
10✔
264
      BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
6✔
265
      nonOrderedPostProcessors.add(pp);
4✔
266
      if (pp instanceof MergedBeanDefinitionPostProcessor) {
3✔
267
        internalPostProcessors.add(pp);
4✔
268
      }
269
    }
1✔
270
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
3✔
271

272
    // Finally, re-register all internal BeanPostProcessors.
273
    sortPostProcessors(internalPostProcessors, beanFactory);
3✔
274
    registerBeanPostProcessors(beanFactory, internalPostProcessors);
3✔
275

276
    // Re-register post-processor for detecting inner beans as ApplicationListeners,
277
    // moving it to the end of the processor chain (for picking up proxies etc).
278
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
6✔
279
  }
1✔
280

281
  /**
282
   * Load and sort the post-processors of the specified type.
283
   *
284
   * @param beanFactory the bean factory to use
285
   * @param beanPostProcessorType the post-processor type
286
   * @param <T> the post-processor type
287
   * @return a list of sorted post-processors for the specified type
288
   */
289
  static <T extends BeanPostProcessor> List<T> loadBeanPostProcessors(
290
          ConfigurableBeanFactory beanFactory, Class<T> beanPostProcessorType) {
291

292
    var postProcessorNames = beanFactory.getBeanNamesForType(beanPostProcessorType, true, false);
6✔
293
    List<T> postProcessors = new ArrayList<>();
4✔
294
    for (String ppName : postProcessorNames) {
16✔
295
      postProcessors.add(beanFactory.getBean(ppName, beanPostProcessorType));
8✔
296
    }
297
    sortPostProcessors(postProcessors, beanFactory);
3✔
298
    return postProcessors;
2✔
299

300
  }
301

302
  /**
303
   * Selectively invoke {@link MergedBeanDefinitionPostProcessor} instances
304
   * registered in the specified bean factory, resolving bean definitions and
305
   * any attributes if necessary as well as any inner bean definitions that
306
   * they may contain.
307
   *
308
   * @param beanFactory the bean factory to use
309
   */
310
  static void invokeMergedBeanDefinitionPostProcessors(StandardBeanFactory beanFactory) {
311
    new MergedBeanDefinitionPostProcessorInvoker(beanFactory).invokeMergedBeanDefinitionPostProcessors();
5✔
312
  }
1✔
313

314
  private static void sortPostProcessors(List<?> postProcessors, ConfigurableBeanFactory beanFactory) {
315
    // Nothing to sort?
316
    if (postProcessors.size() <= 1) {
4✔
317
      return;
1✔
318
    }
319
    Comparator<Object> comparatorToUse = null;
2✔
320
    if (beanFactory instanceof StandardBeanFactory std) {
6!
321
      comparatorToUse = std.getDependencyComparator();
3✔
322
    }
323
    if (comparatorToUse == null) {
2✔
324
      comparatorToUse = OrderComparator.INSTANCE;
2✔
325
    }
326
    postProcessors.sort(comparatorToUse);
3✔
327
  }
1✔
328

329
  /**
330
   * Invoke the given BeanDefinitionRegistryPostProcessor beans.
331
   */
332
  private static void invokeBeanDefinitionRegistryPostProcessors(
333
          Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
334

335
    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
10✔
336
      postProcessor.postProcessBeanDefinitionRegistry(registry);
3✔
337
    }
1✔
338
  }
1✔
339

340
  /**
341
   * Invoke the given BeanFactoryPostProcessor beans.
342
   */
343
  private static void invokeBeanFactoryPostProcessors(
344
          Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableBeanFactory beanFactory) {
345

346
    for (BeanFactoryPostProcessor postProcessor : postProcessors) {
10✔
347
      postProcessor.postProcessBeanFactory(beanFactory);
3✔
348
    }
1✔
349
  }
1✔
350

351
  /**
352
   * Register the given BeanPostProcessor beans.
353
   */
354
  private static void registerBeanPostProcessors(
355
          ConfigurableBeanFactory beanFactory, List<? extends BeanPostProcessor> postProcessors) {
356

357
    if (beanFactory instanceof AbstractBeanFactory abstractBeanFactory) {
6!
358
      // Bulk addition is more efficient against our list there
359
      abstractBeanFactory.addBeanPostProcessors(postProcessors);
4✔
360
    }
361
    else {
362
      for (BeanPostProcessor postProcessor : postProcessors) {
×
363
        beanFactory.addBeanPostProcessor(postProcessor);
×
364
      }
×
365
    }
366
  }
1✔
367

368
  /**
369
   * BeanPostProcessor that logs an info message when a bean is created during
370
   * BeanPostProcessor instantiation, i.e. when a bean is not eligible for
371
   * getting processed by all BeanPostProcessors.
372
   */
373
  private static final class BeanPostProcessorChecker implements InitializationBeanPostProcessor {
374
    private static final Logger log = LoggerFactory.getLogger(BeanPostProcessorChecker.class);
4✔
375

376
    private final ConfigurableBeanFactory beanFactory;
377

378
    private final String[] postProcessorNames;
379

380
    private final int beanPostProcessorTargetCount;
381

382
    public BeanPostProcessorChecker(ConfigurableBeanFactory beanFactory,
383
            String[] postProcessorNames, int beanPostProcessorTargetCount) {
2✔
384

385
      this.beanFactory = beanFactory;
3✔
386
      this.postProcessorNames = postProcessorNames;
3✔
387
      this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;
3✔
388
    }
1✔
389

390
    @Override
391
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
392
      return bean;
2✔
393
    }
394

395
    @Override
396
    public Object postProcessAfterInitialization(Object bean, String beanName) {
397
      if (!(bean instanceof BeanPostProcessor)
5✔
398
              && !isInfrastructureBean(beanName)
4✔
399
              && this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
4✔
400
        if (log.isWarnEnabled()) {
3✔
401
          Set<String> bppsInCreation = new LinkedHashSet<>(2);
5✔
402
          for (String bppName : this.postProcessorNames) {
17✔
403
            if (this.beanFactory.isCurrentlyInCreation(bppName)) {
5✔
404
              bppsInCreation.add(bppName);
4✔
405
            }
406
          }
407
          if (bppsInCreation.size() == 1) {
4!
408
            String bppName = bppsInCreation.iterator().next();
5✔
409
            if (this.beanFactory.containsBeanDefinition(bppName) &&
9!
410
                    beanName.equals(this.beanFactory.getBeanDefinition(bppName).getFactoryBeanName())) {
4✔
411
              log.warn("Bean '{}' of type [{}] is not eligible for getting processed by all BeanPostProcessors " +
12✔
412
                              "(for example: not eligible for auto-proxying). The currently created " +
413
                              "BeanPostProcessor {} is declared through a non-static " +
414
                              "factory method on that class; consider declaring it as static instead.",
415
                      beanName, bean.getClass().getName(), bppsInCreation);
7✔
416
              return bean;
2✔
417
            }
418
          }
419
          log.warn("Bean '{}' of type [{}] is not eligible for getting processed by all BeanPostProcessors " +
12✔
420
                          "(for example: not eligible for auto-proxying). Is this bean getting eagerly " +
421
                          "injected/applied to a currently created BeanPostProcessor {}? " +
422
                          "Check the corresponding BeanPostProcessor declaration and its dependencies/advisors. " +
423
                          "If this bean does not have to be post-processed, declare it with ROLE_INFRASTRUCTURE.",
424
                  beanName, bean.getClass().getName(), bppsInCreation);
7✔
425
        }
426
      }
427
      return bean;
2✔
428
    }
429

430
    private boolean isInfrastructureBean(@Nullable String beanName) {
431
      if (beanName != null && this.beanFactory.containsBeanDefinition(beanName)) {
7✔
432
        BeanDefinition bd = this.beanFactory.getBeanDefinition(beanName);
5✔
433
        return (bd.getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
8✔
434
      }
435
      return false;
2✔
436
    }
437
  }
438

439
  private static final class MergedBeanDefinitionPostProcessorInvoker {
440

441
    private final StandardBeanFactory beanFactory;
442

443
    private MergedBeanDefinitionPostProcessorInvoker(StandardBeanFactory beanFactory) {
2✔
444
      this.beanFactory = beanFactory;
3✔
445
    }
1✔
446

447
    private void invokeMergedBeanDefinitionPostProcessors() {
448
      var postProcessors = PostProcessorRegistrationDelegate.loadBeanPostProcessors(
5✔
449
              this.beanFactory, MergedBeanDefinitionPostProcessor.class);
450
      for (String beanName : this.beanFactory.getBeanDefinitionNames()) {
18✔
451
        RootBeanDefinition bd = (RootBeanDefinition) this.beanFactory.getMergedBeanDefinition(beanName);
6✔
452
        Class<?> beanType = resolveBeanType(bd);
4✔
453
        postProcessRootBeanDefinition(postProcessors, beanName, beanType, bd);
6✔
454
        bd.markAsPostProcessed();
2✔
455
      }
456
      registerBeanPostProcessors(beanFactory, postProcessors);
4✔
457
    }
1✔
458

459
    private void postProcessRootBeanDefinition(List<MergedBeanDefinitionPostProcessor> postProcessors,
460
            String beanName, Class<?> beanType, RootBeanDefinition bd) {
461
      BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(beanFactory, beanName, bd);
8✔
462

463
      for (MergedBeanDefinitionPostProcessor postProcessor : postProcessors) {
10✔
464
        postProcessor.postProcessMergedBeanDefinition(bd, beanType, beanName);
5✔
465
      }
1✔
466

467
      if (bd.hasPropertyValues()) {
3✔
468
        for (PropertyValue propertyValue : bd.getPropertyValues().asList()) {
12✔
469
          postProcessValue(postProcessors, valueResolver, propertyValue.getValue());
6✔
470
        }
1✔
471
      }
472

473
      if (bd.hasConstructorArgumentValues()) {
3✔
474
        for (ValueHolder valueHolder : bd.getConstructorArgumentValues().getIndexedArgumentValues().values()) {
13✔
475
          postProcessValue(postProcessors, valueResolver, valueHolder.getValue());
6✔
476
        }
1✔
477
        for (ValueHolder valueHolder : bd.getConstructorArgumentValues().getGenericArgumentValues()) {
12✔
478
          postProcessValue(postProcessors, valueResolver, valueHolder.getValue());
6✔
479
        }
1✔
480
      }
481
    }
1✔
482

483
    private void postProcessValue(List<MergedBeanDefinitionPostProcessor> postProcessors,
484
            BeanDefinitionValueResolver valueResolver, @Nullable Object value) {
485
      if (value instanceof BeanDefinitionHolder bdh
6✔
486
              && bdh.getBeanDefinition() instanceof AbstractBeanDefinition innerBd) {
9!
487
        Class<?> innerBeanType = resolveBeanType(innerBd);
4✔
488
        resolveInnerBeanDefinition(valueResolver, innerBd, (innerBeanName, innerBeanDefinition)
8✔
489
                -> postProcessRootBeanDefinition(postProcessors, innerBeanName, innerBeanType, innerBeanDefinition));
7✔
490
      }
1✔
491
      else if (value instanceof AbstractBeanDefinition innerBd) {
6✔
492
        Class<?> innerBeanType = resolveBeanType(innerBd);
4✔
493
        resolveInnerBeanDefinition(valueResolver, innerBd, (innerBeanName, innerBeanDefinition)
8✔
494
                -> postProcessRootBeanDefinition(postProcessors, innerBeanName, innerBeanType, innerBeanDefinition));
7✔
495
      }
1✔
496
      else if (value instanceof TypedStringValue typedStringValue) {
6✔
497
        resolveTypeStringValue(typedStringValue);
3✔
498
      }
499
    }
1✔
500

501
    private void resolveInnerBeanDefinition(BeanDefinitionValueResolver valueResolver, BeanDefinition innerBeanDefinition,
502
            BiConsumer<String, RootBeanDefinition> resolver) {
503

504
      valueResolver.resolveInnerBean(null, innerBeanDefinition, (name, rbd) -> {
7✔
505
        resolver.accept(name, rbd);
4✔
506
        return Void.class;
2✔
507
      });
508
    }
1✔
509

510
    private void resolveTypeStringValue(TypedStringValue typedStringValue) {
511
      try {
512
        typedStringValue.resolveTargetType(this.beanFactory.getBeanClassLoader());
6✔
513
      }
514
      catch (ClassNotFoundException ex) {
×
515
        // ignore
516
      }
1✔
517
    }
1✔
518

519
    private Class<?> resolveBeanType(AbstractBeanDefinition bd) {
520
      if (!bd.hasBeanClass()) {
3✔
521
        try {
522
          bd.resolveBeanClass(this.beanFactory.getBeanClassLoader());
6✔
523
        }
524
        catch (ClassNotFoundException ex) {
×
525
          // ignore
526
        }
1✔
527
      }
528
      return bd.getResolvableType().toClass();
4✔
529
    }
530
  }
531

532
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc