Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DubboConfigEarlyInitializationPostProcessor counted as BeanPostProcessor twice. Cause print log 'is not eligible for getting processed by all BeanPostProcessors' during most spring bean Initialization #9370

Closed
gitchenjh opened this issue Dec 9, 2021 · 3 comments
Labels
type/bug Bugs to being fixed

Comments

@gitchenjh
Copy link
Contributor

gitchenjh commented Dec 9, 2021

see also #8347

Environment

  • Dubbo version: 2.7.14
  • Operating System version: Windows 10 Build: 19044.1387
  • Java version: 1.8.0_211

Steps to reproduce this issue

  1. bootup a spring-boot application with dubbo-spring-boot-starter 2.7.14
  2. the application print log like this
BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat' of type [org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

Provide [GitHub address] to reproduce this issue.
https://github.com/gitchenjh/dubbo-test

Expected Behavior

DubboConfigEarlyInitializationPostProcessor shuold only counted as BeanPostProcessor once in PostProcessorRegistrationDelegate.registerBeanPostProcessors()

Actual Behavior

DubboConfigEarlyInitializationPostProcessor counted as BeanPostProcessor twice in PostProcessorRegistrationDelegate.registerBeanPostProcessors()

first time addBeanPostProcessor

    // org.apache.dubbo.config.spring.beans.factory.config.DubboConfigEarlyInitializationPostProcessor
    private void initBeanFactory() {
        if (beanFactory != null) {
            // Register itself
            if (logger.isInfoEnabled()) {
                logger.info("BeanFactory is about to be initialized, trying to resolve the Dubbo Config Beans early " +
                        "initialization");
            }
            beanFactory.addBeanPostProcessor(this);
        }
    }

image

counted as BeanPostProcessor twice

        // org.springframework.context.support.PostProcessorRegistrationDelegate
	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		// WARNING: Although it may appear that the body of this method can be easily
		// refactored to avoid the use of multiple loops and multiple lists, the use
		// of multiple lists and multiple passes over the names of processors is
		// intentional. We must ensure that we honor the contracts for PriorityOrdered
		// and Ordered processors. Specifically, we must NOT cause processors to be
		// instantiated (via getBean() invocations) or registered in the ApplicationContext
		// in the wrong order.
		//
		// Before submitting a pull request (PR) to change this method, please review the
		// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
		// to ensure that your proposal does not result in a breaking change:
		// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// 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));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    }

image

DubboConfigEarlyInitializationPostProcessor has added as BeanPostProcessor into DefaultListableBeanFactory, beanFactory.getBeanPostProcessorCount() has counted once, but beanFactory.getBeanNamesForType() counted it again

        // org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors
        // First, register the BeanPostProcessors that implement PriorityOrdered.
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
        
        //org.springframework.beans.factory.support.AbstractBeanFactory
	public void addBeanPostProcessors(Collection<? extends BeanPostProcessor> beanPostProcessors) {
		this.beanPostProcessors.removeAll(beanPostProcessors);
		this.beanPostProcessors.addAll(beanPostProcessors);
	}

image

this.beanPostProcessors.removeAl will remove DubboConfigEarlyInitializationPostProcessor
this.beanPostProcessors.addAll will add DubboConfigEarlyInitializationPostProcessor again
so there is only one DubboConfigEarlyInitializationPostProcessor instance in DefaultListableBeanFactory.beanPostProcessors,but beanProcessorTargetCount counted is twice

                // org.springframework.context.support.PostProcessorRegistrationDelegate.BeanPostProcessorChecker
		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() +
							"] is not eligible for getting processed by all BeanPostProcessors " +
							"(for example: not eligible for auto-proxying)");
				}
			}
			return bean;
		}

image

The this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount will always be true
so after BeanPostProcessorChecker added into DefaultListableBeanFactory.beanPostProcessors,during every spring bean initialization, there will print log

BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat' of type [org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
@baymax55
Copy link

是不是在配置文件中使用@DubboReference注解,导致bean加载太早

@gitchenjh
Copy link
Contributor Author

gitchenjh commented Dec 13, 2021

是不是在配置文件中使用@DubboReference注解,导致bean加载太早

不是,就Spring-Boot启动类引入 @EnableDubbo
image
image
image

可以直接用这个链接验证,一个空的Spring-Boot项目,加dubbo-spring-boot-starter依赖
https://github.com/gitchenjh/dubbo-test

chickenlj pushed a commit that referenced this issue Dec 15, 2021
@chickenlj
Copy link
Contributor

fixed with #9397

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/bug Bugs to being fixed
Projects
None yet
Development

No branches or pull requests

3 participants