Remove instance suppliers in bean definitions

Remove instance suppliers in bean definitions and depend instead
on reflection. This allows the AOT engine to correctly process
the definitions.

Fixes gh-33763
pull/33886/head
Moritz Halbritter 2 years ago committed by Phillip Webb
parent 71efc55bf9
commit ae79c60619

@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-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.
@ -16,8 +16,6 @@
package org.springframework.boot.autoconfigure.web.reactive;
import java.util.function.Supplier;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
@ -102,14 +100,13 @@ public class ReactiveWebServerFactoryAutoConfiguration {
return;
}
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class,
WebServerFactoryCustomizerBeanPostProcessor::new);
WebServerFactoryCustomizerBeanPostProcessor.class);
}
private <T> void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name,
Class<T> beanClass, Supplier<T> instanceSupplier) {
Class<T> beanClass) {
if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass, instanceSupplier);
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(name, beanDefinition);
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-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.
@ -16,8 +16,6 @@
package org.springframework.boot.autoconfigure.web.servlet;
import java.util.function.Supplier;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.ServletRequest;
@ -139,16 +137,15 @@ public class ServletWebServerFactoryAutoConfiguration {
return;
}
registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
WebServerFactoryCustomizerBeanPostProcessor.class,
WebServerFactoryCustomizerBeanPostProcessor::new);
WebServerFactoryCustomizerBeanPostProcessor.class);
registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
ErrorPageRegistrarBeanPostProcessor.class, ErrorPageRegistrarBeanPostProcessor::new);
ErrorPageRegistrarBeanPostProcessor.class);
}
private <T> void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name,
Class<T> beanClass, Supplier<T> instanceSupplier) {
Class<T> beanClass) {
if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass, instanceSupplier);
RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
beanDefinition.setSynthetic(true);
registry.registerBeanDefinition(name, beanDefinition);
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-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.
@ -81,8 +81,7 @@ public class BoundConfigurationProperties {
static void register(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "Registry must not be null");
if (!registry.containsBeanDefinition(BEAN_NAME)) {
BeanDefinition definition = BeanDefinitionBuilder
.genericBeanDefinition(BoundConfigurationProperties.class, BoundConfigurationProperties::new)
BeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition(BoundConfigurationProperties.class)
.getBeanDefinition();
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(BEAN_NAME, definition);

@ -1,5 +1,5 @@
/*
* Copyright 2012-2022 the original author or authors.
* Copyright 2012-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.
@ -50,6 +50,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.PropertySources;
import org.springframework.util.Assert;
import org.springframework.validation.Validator;
import org.springframework.validation.annotation.Validated;
@ -64,8 +65,6 @@ class ConfigurationPropertiesBinder {
private static final String BEAN_NAME = "org.springframework.boot.context.internalConfigurationPropertiesBinder";
private static final String FACTORY_BEAN_NAME = "org.springframework.boot.context.internalConfigurationPropertiesBinderFactory";
private static final String VALIDATOR_BEAN_NAME = EnableConfigurationProperties.VALIDATOR_BEAN_NAME;
private final ApplicationContext applicationContext;
@ -189,18 +188,9 @@ class ConfigurationPropertiesBinder {
}
static void register(BeanDefinitionRegistry registry) {
if (!registry.containsBeanDefinition(FACTORY_BEAN_NAME)) {
BeanDefinition definition = BeanDefinitionBuilder
.rootBeanDefinition(ConfigurationPropertiesBinder.Factory.class).getBeanDefinition();
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(ConfigurationPropertiesBinder.FACTORY_BEAN_NAME, definition);
}
if (!registry.containsBeanDefinition(BEAN_NAME)) {
BeanDefinition definition = BeanDefinitionBuilder
.rootBeanDefinition(ConfigurationPropertiesBinder.class,
() -> ((BeanFactory) registry)
.getBean(FACTORY_BEAN_NAME, ConfigurationPropertiesBinder.Factory.class).create())
.getBeanDefinition();
.rootBeanDefinition(ConfigurationPropertiesBinderFactory.class).getBeanDefinition();
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(ConfigurationPropertiesBinder.BEAN_NAME, definition);
}
@ -211,44 +201,49 @@ class ConfigurationPropertiesBinder {
}
/**
* Factory bean used to create the {@link ConfigurationPropertiesBinder}. The bean
* needs to be {@link ApplicationContextAware} since we can't directly inject an
* {@link ApplicationContext} into the constructor without causing eager
* {@link FactoryBean} initialization.
* {@link BindHandler} to deal with
* {@link ConfigurationProperties @ConfigurationProperties} concerns.
*/
static class Factory implements ApplicationContextAware {
private static class ConfigurationPropertiesBindHandler extends AbstractBindHandler {
private ApplicationContext applicationContext;
ConfigurationPropertiesBindHandler(BindHandler handler) {
super(handler);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
public <T> Bindable<T> onStart(ConfigurationPropertyName name, Bindable<T> target, BindContext context) {
return isConfigurationProperties(target.getType().resolve())
? target.withBindRestrictions(BindRestriction.NO_DIRECT_PROPERTY) : target;
}
ConfigurationPropertiesBinder create() {
return new ConfigurationPropertiesBinder(this.applicationContext);
private boolean isConfigurationProperties(Class<?> target) {
return target != null && MergedAnnotations.from(target).isPresent(ConfigurationProperties.class);
}
}
/**
* {@link BindHandler} to deal with
* {@link ConfigurationProperties @ConfigurationProperties} concerns.
* {@link FactoryBean} to create the {@link ConfigurationPropertiesBinder}.
*/
private static class ConfigurationPropertiesBindHandler extends AbstractBindHandler {
static class ConfigurationPropertiesBinderFactory
implements FactoryBean<ConfigurationPropertiesBinder>, ApplicationContextAware {
ConfigurationPropertiesBindHandler(BindHandler handler) {
super(handler);
private ConfigurationPropertiesBinder binder;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.binder = (this.binder != null) ? this.binder : new ConfigurationPropertiesBinder(applicationContext);
}
@Override
public <T> Bindable<T> onStart(ConfigurationPropertyName name, Bindable<T> target, BindContext context) {
return isConfigurationProperties(target.getType().resolve())
? target.withBindRestrictions(BindRestriction.NO_DIRECT_PROPERTY) : target;
public Class<?> getObjectType() {
return ConfigurationPropertiesBinder.class;
}
private boolean isConfigurationProperties(Class<?> target) {
return target != null && MergedAnnotations.from(target).isPresent(ConfigurationProperties.class);
@Override
public ConfigurationPropertiesBinder getObject() throws Exception {
Assert.state(this.binder != null, "Binder was not created due to missing setApplicationContext call");
return this.binder;
}
}

Loading…
Cancel
Save