Skip to content

Commit

Permalink
Merge branch '3.0.x'
Browse files Browse the repository at this point in the history
Closes gh-35647
  • Loading branch information
wilkinsona committed May 26, 2023
2 parents 1d2a41f + 5ad0d49 commit 127004b
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -24,9 +24,10 @@
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
import org.springframework.beans.factory.aot.BeanFactoryInitializationCode;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.context.properties.bind.BindMethod;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrar;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;

/**
* {@link BeanFactoryInitializationAotProcessor} that contributes runtime hints for
Expand All @@ -43,36 +44,38 @@ class ConfigurationPropertiesBeanFactoryInitializationAotProcessor implements Be
public ConfigurationPropertiesReflectionHintsContribution processAheadOfTime(
ConfigurableListableBeanFactory beanFactory) {
String[] beanNames = beanFactory.getBeanNamesForAnnotation(ConfigurationProperties.class);
List<Class<?>> types = new ArrayList<>();
List<Bindable<?>> bindables = new ArrayList<>();
for (String beanName : beanNames) {
Class<?> beanType = beanFactory.getType(beanName, false);
if (beanType != null) {
types.add(ClassUtils.getUserClass(beanType));
BindMethod bindMethod = beanFactory.containsBeanDefinition(beanName)
? (BindMethod) beanFactory.getBeanDefinition(beanName).getAttribute(BindMethod.class.getName())
: null;
bindables.add(Bindable.of(ClassUtils.getUserClass(beanType))
.withBindMethod((bindMethod != null) ? bindMethod : BindMethod.JAVA_BEAN));
}
}
if (!CollectionUtils.isEmpty(types)) {
return new ConfigurationPropertiesReflectionHintsContribution(types);
}
return null;
return (!bindables.isEmpty()) ? new ConfigurationPropertiesReflectionHintsContribution(bindables) : null;
}

static final class ConfigurationPropertiesReflectionHintsContribution
implements BeanFactoryInitializationAotContribution {

private final Iterable<Class<?>> types;
private final List<Bindable<?>> bindables;

private ConfigurationPropertiesReflectionHintsContribution(Iterable<Class<?>> types) {
this.types = types;
private ConfigurationPropertiesReflectionHintsContribution(List<Bindable<?>> bindables) {
this.bindables = bindables;
}

@Override
public void applyTo(GenerationContext generationContext,
BeanFactoryInitializationCode beanFactoryInitializationCode) {
BindableRuntimeHintsRegistrar.forTypes(this.types).registerHints(generationContext.getRuntimeHints());
BindableRuntimeHintsRegistrar.forBindables(this.bindables)
.registerHints(generationContext.getRuntimeHints());
}

Iterable<Class<?>> getTypes() {
return this.types;
Iterable<Bindable<?>> getBindables() {
return this.bindables;
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import kotlin.jvm.JvmClassMappingKt;
Expand Down Expand Up @@ -51,8 +52,8 @@
* {@link RuntimeHintsRegistrar} that can be used to register {@link ReflectionHints} for
* {@link Bindable} types, discovering any nested type it may expose through a property.
* <p>
* This class can be used as a base-class, or instantiated using the {@code forTypes}
* factory methods.
* This class can be used as a base-class, or instantiated using the {@code forTypes} and
* {@code forBindables} factory methods.
*
* @author Andy Wilkinson
* @author Moritz Halbritter
Expand All @@ -62,14 +63,23 @@
*/
public class BindableRuntimeHintsRegistrar implements RuntimeHintsRegistrar {

private final Class<?>[] types;
private final Bindable<?>[] bindables;

/**
* Create a new {@link BindableRuntimeHintsRegistrar} for the specified types.
* @param types the types to process
*/
protected BindableRuntimeHintsRegistrar(Class<?>... types) {
this.types = types;
this(Stream.of(types).map(Bindable::of).toArray(Bindable[]::new));
}

/**
* Create a new {@link BindableRuntimeHintsRegistrar} for the specified bindables.
* @param bindables the bindables to process
* @since 3.0.8
*/
protected BindableRuntimeHintsRegistrar(Bindable<?>... bindables) {
this.bindables = bindables;
}

@Override
Expand All @@ -83,8 +93,8 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
*/
public void registerHints(RuntimeHints hints) {
Set<Class<?>> compiledWithoutParameters = new HashSet<>();
for (Class<?> type : this.types) {
new Processor(type, compiledWithoutParameters).process(hints.reflection());
for (Bindable<?> bindable : this.bindables) {
new Processor(bindable, compiledWithoutParameters).process(hints.reflection());
}
if (!compiledWithoutParameters.isEmpty()) {
throw new MissingParametersCompilerArgumentException(compiledWithoutParameters);
Expand All @@ -110,6 +120,27 @@ public static BindableRuntimeHintsRegistrar forTypes(Class<?>... types) {
return new BindableRuntimeHintsRegistrar(types);
}

/**
* Create a new {@link BindableRuntimeHintsRegistrar} for the specified bindables.
* @param bindables the bindables to process
* @return a new {@link BindableRuntimeHintsRegistrar} instance
* @since 3.0.8
*/
public static BindableRuntimeHintsRegistrar forBindables(Iterable<Bindable<?>> bindables) {
Assert.notNull(bindables, "Bindables must not be null");
return forBindables(StreamSupport.stream(bindables.spliterator(), false).toArray(Bindable[]::new));
}

/**
* Create a new {@link BindableRuntimeHintsRegistrar} for the specified bindables.
* @param bindables the bindables to process
* @return a new {@link BindableRuntimeHintsRegistrar} instance
* @since 3.0.8
*/
public static BindableRuntimeHintsRegistrar forBindables(Bindable<?>... bindables) {
return new BindableRuntimeHintsRegistrar(bindables);
}

/**
* Processor used to register the hints.
*/
Expand All @@ -136,15 +167,17 @@ private final class Processor {

private final Set<Class<?>> compiledWithoutParameters;

Processor(Class<?> type, Set<Class<?>> compiledWithoutParameters) {
this(type, false, new HashSet<>(), compiledWithoutParameters);
Processor(Bindable<?> bindable, Set<Class<?>> compiledWithoutParameters) {
this(bindable, false, new HashSet<>(), compiledWithoutParameters);
}

private Processor(Class<?> type, boolean nestedType, Set<Class<?>> seen,
private Processor(Bindable<?> bindable, boolean nestedType, Set<Class<?>> seen,
Set<Class<?>> compiledWithoutParameters) {
this.type = type;
this.bindConstructor = BindConstructorProvider.DEFAULT.getBindConstructor(Bindable.of(type), nestedType);
this.bean = JavaBeanBinder.BeanProperties.of(Bindable.of(type));
this.type = bindable.getType().getRawClass();
this.bindConstructor = (bindable.getBindMethod() != BindMethod.JAVA_BEAN)
? BindConstructorProvider.DEFAULT.getBindConstructor(bindable.getType().resolve(), nestedType)
: null;
this.bean = JavaBeanBinder.BeanProperties.of(bindable);
this.seen = seen;
this.compiledWithoutParameters = compiledWithoutParameters;
}
Expand Down Expand Up @@ -235,7 +268,7 @@ else if (isNestedType(propertyName, propertyClass)) {
}

private void processNested(Class<?> type, ReflectionHints hints) {
new Processor(type, true, this.seen, this.compiledWithoutParameters).process(hints);
new Processor(Bindable.of(type), true, this.seen, this.compiledWithoutParameters).process(hints);
}

private Class<?> getComponentClass(ResolvableType type) {
Expand Down
Loading

0 comments on commit 127004b

Please sign in to comment.