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 d5b78848768..112e1f5a136 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 the original author or authors. + * Copyright 2002-2023 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. @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.function.BiConsumer; @@ -227,7 +228,8 @@ final class PostProcessorRegistrationDelegate { // a bean is created during BeanPostProcessor instantiation, i.e. when // a bean is not eligible for getting processed by all BeanPostProcessors. int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; - beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); + beanFactory.addBeanPostProcessor( + new BeanPostProcessorChecker(beanFactory, postProcessorNames, beanProcessorTargetCount)); // Separate between BeanPostProcessors that implement PriorityOrdered, // Ordered, and the rest. @@ -389,10 +391,15 @@ final class PostProcessorRegistrationDelegate { private final ConfigurableListableBeanFactory beanFactory; + private final String[] postProcessorNames; + private final int beanPostProcessorTargetCount; - public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) { + public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, + String[] postProcessorNames, int beanPostProcessorTargetCount) { + this.beanFactory = beanFactory; + this.postProcessorNames = postProcessorNames; this.beanPostProcessorTargetCount = beanPostProcessorTargetCount; } @@ -405,10 +412,30 @@ final class PostProcessorRegistrationDelegate { public Object postProcessAfterInitialization(Object bean, String beanName) { if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) && this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) { - if (logger.isInfoEnabled()) { - logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() + + if (logger.isWarnEnabled()) { + Set bppsInCreation = new LinkedHashSet<>(2); + for (String bppName : this.postProcessorNames) { + if (this.beanFactory.isCurrentlyInCreation(bppName)) { + bppsInCreation.add(bppName); + } + } + if (bppsInCreation.size() == 1) { + String bppName = bppsInCreation.iterator().next(); + if (this.beanFactory.containsBeanDefinition(bppName) && + beanName.equals(this.beanFactory.getBeanDefinition(bppName).getFactoryBeanName())) { + logger.warn("Bean '" + beanName + "' of type [" + bean.getClass().getName() + + "] is not eligible for getting processed by all BeanPostProcessors " + + "(for example: not eligible for auto-proxying). The currently created " + + "BeanPostProcessor " + bppsInCreation + " is declared through a non-static " + + "factory method on that class; consider declaring it as static instead."); + return bean; + } + } + logger.warn("Bean '" + beanName + "' of type [" + bean.getClass().getName() + "] is not eligible for getting processed by all BeanPostProcessors " + - "(for example: not eligible for auto-proxying)"); + "(for example: not eligible for auto-proxying). Is this bean getting eagerly " + + "injected into a currently created BeanPostProcessor " + bppsInCreation + "? " + + "Check the corresponding BeanPostProcessor declaration and its dependencies."); } } return bean;