Browse Source

Expose registrar for @Reflective

This commit exposes the logic of processing `@Reflective` on beans so
that it can be reused in custom arrangements.

Closes gh-28975
pull/28987/head
Stephane Nicoll 3 years ago
parent
commit
4556895e6e
  1. 68
      spring-context/src/main/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessor.java
  2. 4
      spring-context/src/main/resources/META-INF/spring/aot.factories
  3. 107
      spring-context/src/test/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessorTests.java
  4. 1
      spring-core/src/main/java/org/springframework/aot/hint/annotation/Reflective.java
  5. 101
      spring-core/src/main/java/org/springframework/aot/hint/annotation/ReflectiveRuntimeHintsRegistrar.java
  6. 56
      spring-core/src/test/java/org/springframework/aot/hint/annotation/ReflectiveRuntimeHintsRegistrarTests.java

68
spring-context/src/main/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessor.java

@ -0,0 +1,68 @@ @@ -0,0 +1,68 @@
/*
* Copyright 2002-2022 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.aot;
import java.util.Arrays;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.aot.hint.annotation.ReflectiveProcessor;
import org.springframework.aot.hint.annotation.ReflectiveRuntimeHintsRegistrar;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
import org.springframework.beans.factory.aot.BeanFactoryInitializationCode;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.RegisteredBean;
/**
* AOT {@code BeanFactoryInitializationAotProcessor} that detects the presence
* of {@link Reflective @Reflective} on annotated elements of all registered
* beans and invokes the underlying {@link ReflectiveProcessor} implementations.
*
* @author Stephane Nicoll
* @author Sebastien Deleuze
*/
class ReflectiveProcessorBeanFactoryInitializationAotProcessor implements BeanFactoryInitializationAotProcessor {
private static final ReflectiveRuntimeHintsRegistrar REGISTRAR = new ReflectiveRuntimeHintsRegistrar();
@Override
public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) {
Class<?>[] beanTypes = Arrays.stream(beanFactory.getBeanDefinitionNames())
.map(beanName -> RegisteredBean.of(beanFactory, beanName).getBeanClass())
.toArray(Class<?>[]::new);
return new ReflectiveProcessorBeanFactoryInitializationAotContribution(beanTypes);
}
private static class ReflectiveProcessorBeanFactoryInitializationAotContribution implements BeanFactoryInitializationAotContribution {
private final Class<?>[] types;
public ReflectiveProcessorBeanFactoryInitializationAotContribution(Class<?>[] types) {
this.types = types;
}
@Override
public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) {
RuntimeHints runtimeHints = generationContext.getRuntimeHints();
REGISTRAR.registerRuntimeHints(runtimeHints, this.types);
}
}
}

4
spring-context/src/main/resources/META-INF/spring/aot.factories

@ -1,3 +1,5 @@ @@ -1,3 +1,5 @@
org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor= \
org.springframework.context.aot.ReflectiveProcessorBeanFactoryInitializationAotProcessor
org.springframework.beans.factory.aot.BeanRegistrationAotProcessor= \
org.springframework.context.aot.ReflectiveProcessorBeanRegistrationAotProcessor,\
org.springframework.cache.annotation.CachingBeanRegistrationAotProcessor

107
spring-context/src/test/java/org/springframework/context/aot/ReflectiveProcessorBeanFactoryInitializationAotProcessorTests.java

@ -0,0 +1,107 @@ @@ -0,0 +1,107 @@
/*
* Copyright 2002-2022 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.aot;
import java.lang.reflect.Constructor;
import org.junit.jupiter.api.Test;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.aot.hint.predicate.ReflectionHintsPredicates;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.beans.factory.aot.AotServices;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
import org.springframework.beans.factory.aot.BeanFactoryInitializationCode;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.testfixture.aot.generate.TestGenerationContext;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link ReflectiveProcessorBeanFactoryInitializationAotProcessor}.
*
* @author Stephane Nicoll
* @author Sebastien Deleuze
*/
class ReflectiveProcessorBeanFactoryInitializationAotProcessorTests {
private final ReflectiveProcessorBeanFactoryInitializationAotProcessor processor = new ReflectiveProcessorBeanFactoryInitializationAotProcessor();
private final GenerationContext generationContext = new TestGenerationContext();
@Test
void processorIsRegistered() {
assertThat(AotServices.factories(getClass().getClassLoader()).load(BeanFactoryInitializationAotProcessor.class))
.anyMatch(ReflectiveProcessorBeanFactoryInitializationAotProcessor.class::isInstance);
}
@Test
void shouldProcessAnnotationOnType() {
process(SampleTypeAnnotatedBean.class);
assertThat(RuntimeHintsPredicates.reflection().onType(SampleTypeAnnotatedBean.class))
.accepts(this.generationContext.getRuntimeHints());
}
@Test
void shouldProcessAllBeans() throws NoSuchMethodException {
ReflectionHintsPredicates reflection = RuntimeHintsPredicates.reflection();
process(SampleTypeAnnotatedBean.class, SampleConstructorAnnotatedBean.class);
Constructor<?> constructor = SampleConstructorAnnotatedBean.class.getDeclaredConstructor(String.class);
assertThat(reflection.onType(SampleTypeAnnotatedBean.class).and(reflection.onConstructor(constructor)))
.accepts(this.generationContext.getRuntimeHints());
}
private void process(Class<?>... beanClasses) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
for (Class<?> beanClass : beanClasses) {
beanFactory.registerBeanDefinition(beanClass.getName(), new RootBeanDefinition(beanClass));
}
BeanFactoryInitializationAotContribution contribution = this.processor.processAheadOfTime(beanFactory);
assertThat(contribution).isNotNull();
contribution.applyTo(this.generationContext, mock(BeanFactoryInitializationCode.class));
}
@Reflective
@SuppressWarnings("unused")
static class SampleTypeAnnotatedBean {
private String notManaged;
public void notManaged() {
}
}
@SuppressWarnings("unused")
static class SampleConstructorAnnotatedBean {
@Reflective
SampleConstructorAnnotatedBean(String name) {
}
SampleConstructorAnnotatedBean(Integer nameAsNumber) {
}
}
}

1
spring-core/src/main/java/org/springframework/aot/hint/annotation/Reflective.java

@ -39,6 +39,7 @@ import org.springframework.core.annotation.AliasFor; @@ -39,6 +39,7 @@ import org.springframework.core.annotation.AliasFor;
* @author Sam Brannen
* @since 6.0
* @see SimpleReflectiveProcessor
* @see ReflectiveRuntimeHintsRegistrar
*/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.CONSTRUCTOR,
ElementType.FIELD, ElementType.METHOD })

101
spring-context/src/main/java/org/springframework/context/aot/ReflectiveProcessorBeanRegistrationAotProcessor.java → spring-core/src/main/java/org/springframework/aot/hint/annotation/ReflectiveRuntimeHintsRegistrar.java

@ -14,60 +14,65 @@ @@ -14,60 +14,65 @@
* limitations under the License.
*/
package org.springframework.context.aot;
package org.springframework.aot.hint.annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.hint.ReflectionHints;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.aot.hint.annotation.ReflectiveProcessor;
import org.springframework.aot.hint.support.RuntimeHintsUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
import org.springframework.beans.factory.aot.BeanRegistrationAotProcessor;
import org.springframework.beans.factory.aot.BeanRegistrationCode;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* AOT {@code BeanRegistrationAotProcessor} that detects the presence of
* {@link Reflective @Reflective} on annotated elements and invokes the
* underlying {@link ReflectiveProcessor} implementations.
* Process {@link Reflective} annotated elements.
*
* @author Stephane Nicoll
* @author Sebastien Deleuze
* since 6.0
*/
class ReflectiveProcessorBeanRegistrationAotProcessor implements BeanRegistrationAotProcessor {
public class ReflectiveRuntimeHintsRegistrar {
private final Map<Class<? extends ReflectiveProcessor>, ReflectiveProcessor> processors = new HashMap<>();
@Nullable
@Override
public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registeredBean) {
Class<?> beanClass = registeredBean.getBeanClass();
Set<Entry> entries = new LinkedHashSet<>();
processType(entries, beanClass);
for (Class<?> implementedInterface : ClassUtils.getAllInterfacesForClass(beanClass)) {
processType(entries, implementedInterface);
}
if (!entries.isEmpty()) {
return new ReflectiveProcessorBeanRegistrationAotContribution(entries);
/**
* Register the relevant runtime hints for elements that are annotated with
* {@link Reflective}.
* @param runtimeHints the runtime hints instance to use
* @param types the types to process
*/
public void registerRuntimeHints(RuntimeHints runtimeHints, Class<?>... types) {
Set<Entry> entries = new HashSet<>();
Arrays.stream(types).forEach(type -> {
processType(entries, type);
for (Class<?> implementedInterface : ClassUtils.getAllInterfacesForClass(type)) {
processType(entries, implementedInterface);
}
});
entries.forEach(entry -> {
AnnotatedElement element = entry.element();
entry.processor().registerReflectionHints(runtimeHints.reflection(), element);
registerAnnotationIfNecessary(runtimeHints, element);
});
}
private void registerAnnotationIfNecessary(RuntimeHints hints, AnnotatedElement element) {
MergedAnnotation<Reflective> reflectiveAnnotation = MergedAnnotations.from(element)
.get(Reflective.class);
MergedAnnotation<?> metaSource = reflectiveAnnotation.getMetaSource();
if (metaSource != null) {
RuntimeHintsUtils.registerAnnotationIfNecessary(hints, metaSource);
}
return null;
}
private void processType(Set<Entry> entries, Class<?> typeToProcess) {
@ -99,13 +104,22 @@ class ReflectiveProcessorBeanRegistrationAotProcessor implements BeanRegistratio @@ -99,13 +104,22 @@ class ReflectiveProcessorBeanRegistrationAotProcessor implements BeanRegistratio
Class<? extends ReflectiveProcessor>[] processorClasses = (Class<? extends ReflectiveProcessor>[])
MergedAnnotations.from(element, MergedAnnotations.SearchStrategy.TYPE_HIERARCHY).get(Reflective.class).getClassArray("value");
List<ReflectiveProcessor> processors = Arrays.stream(processorClasses).distinct()
.map(processorClass -> this.processors.computeIfAbsent(processorClass, BeanUtils::instantiateClass))
.map(processorClass -> this.processors.computeIfAbsent(processorClass, this::instantiateClass))
.toList();
ReflectiveProcessor processorToUse = (processors.size() == 1 ? processors.get(0)
: new DelegateReflectiveProcessor(processors));
return new Entry(element, processorToUse);
}
private ReflectiveProcessor instantiateClass(Class<? extends ReflectiveProcessor> type) {
try {
return type.getDeclaredConstructor().newInstance();
}
catch (Exception ex) {
throw new IllegalStateException("Failed to instantiate " + type, ex);
}
}
static class DelegateReflectiveProcessor implements ReflectiveProcessor {
private final Iterable<ReflectiveProcessor> processors;
@ -123,33 +137,4 @@ class ReflectiveProcessorBeanRegistrationAotProcessor implements BeanRegistratio @@ -123,33 +137,4 @@ class ReflectiveProcessorBeanRegistrationAotProcessor implements BeanRegistratio
private record Entry(AnnotatedElement element, ReflectiveProcessor processor) {}
private static class ReflectiveProcessorBeanRegistrationAotContribution implements BeanRegistrationAotContribution {
private final Iterable<Entry> entries;
public ReflectiveProcessorBeanRegistrationAotContribution(Iterable<Entry> entries) {
this.entries = entries;
}
@Override
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
RuntimeHints runtimeHints = generationContext.getRuntimeHints();
this.entries.forEach(entry -> {
AnnotatedElement element = entry.element();
entry.processor().registerReflectionHints(runtimeHints.reflection(), element);
registerAnnotationIfNecessary(runtimeHints, element);
});
}
private void registerAnnotationIfNecessary(RuntimeHints hints, AnnotatedElement element) {
MergedAnnotation<Reflective> reflectiveAnnotation = MergedAnnotations.from(element)
.get(Reflective.class);
MergedAnnotation<?> metaSource = reflectiveAnnotation.getMetaSource();
if (metaSource != null) {
RuntimeHintsUtils.registerAnnotationIfNecessary(hints, metaSource);
}
}
}
}

56
spring-context/src/test/java/org/springframework/context/aot/ReflectiveProcessorBeanRegistrationAotProcessorTests.java → spring-core/src/test/java/org/springframework/aot/hint/annotation/ReflectiveRuntimeHintsRegistrarTests.java

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.context.aot;
package org.springframework.aot.hint.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
@ -24,52 +24,45 @@ import java.lang.annotation.Target; @@ -24,52 +24,45 @@ import java.lang.annotation.Target;
import org.junit.jupiter.api.Test;
import org.springframework.aot.generate.GenerationContext;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeReference;
import org.springframework.aot.hint.annotation.Reflective;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.beans.factory.aot.BeanRegistrationAotContribution;
import org.springframework.beans.factory.aot.BeanRegistrationCode;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RegisteredBean;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.annotation.SynthesizedAnnotation;
import org.springframework.core.testfixture.aot.generate.TestGenerationContext;
import org.springframework.lang.Nullable;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyNoInteractions;
/**
* Tests for {@link ReflectiveProcessorBeanRegistrationAotProcessor}.
* Tests for {@link ReflectiveRuntimeHintsRegistrar}.
*
* @author Stephane Nicoll
* @author Sebastien Deleuze
*/
class ReflectiveProcessorBeanRegistrationAotProcessorTests {
class ReflectiveRuntimeHintsRegistrarTests {
private final ReflectiveProcessorBeanRegistrationAotProcessor processor = new ReflectiveProcessorBeanRegistrationAotProcessor();
private final ReflectiveRuntimeHintsRegistrar registrar = new ReflectiveRuntimeHintsRegistrar();
private final GenerationContext generationContext = new TestGenerationContext();
private final RuntimeHints runtimeHints = new RuntimeHints();
@Test
void shouldIgnoreNonAnnotatedType() {
assertThat(createContribution(String.class)).isNull();
RuntimeHints mock = mock(RuntimeHints.class);
this.registrar.registerRuntimeHints(mock, String.class);
verifyNoInteractions(mock);
}
@Test
void shouldProcessAnnotationOnType() {
process(SampleTypeAnnotatedBean.class);
assertThat(this.generationContext.getRuntimeHints().reflection().getTypeHint(SampleTypeAnnotatedBean.class))
assertThat(this.runtimeHints.reflection().getTypeHint(SampleTypeAnnotatedBean.class))
.isNotNull();
}
@Test
void shouldProcessAnnotationOnConstructor() {
process(SampleConstructorAnnotatedBean.class);
assertThat(this.generationContext.getRuntimeHints().reflection().getTypeHint(SampleConstructorAnnotatedBean.class))
assertThat(this.runtimeHints.reflection().getTypeHint(SampleConstructorAnnotatedBean.class))
.satisfies(typeHint -> assertThat(typeHint.constructors()).singleElement()
.satisfies(constructorHint -> assertThat(constructorHint.getParameterTypes())
.containsExactly(TypeReference.of(String.class))));
@ -78,7 +71,7 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests { @@ -78,7 +71,7 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests {
@Test
void shouldProcessAnnotationOnField() {
process(SampleFieldAnnotatedBean.class);
assertThat(this.generationContext.getRuntimeHints().reflection().getTypeHint(SampleFieldAnnotatedBean.class))
assertThat(this.runtimeHints.reflection().getTypeHint(SampleFieldAnnotatedBean.class))
.satisfies(typeHint -> assertThat(typeHint.fields()).singleElement()
.satisfies(fieldHint -> assertThat(fieldHint.getName()).isEqualTo("managed")));
}
@ -86,7 +79,7 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests { @@ -86,7 +79,7 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests {
@Test
void shouldProcessAnnotationOnMethod() {
process(SampleMethodAnnotatedBean.class);
assertThat(this.generationContext.getRuntimeHints().reflection().getTypeHint(SampleMethodAnnotatedBean.class))
assertThat(this.runtimeHints.reflection().getTypeHint(SampleMethodAnnotatedBean.class))
.satisfies(typeHint -> assertThat(typeHint.methods()).singleElement()
.satisfies(methodHint -> assertThat(methodHint.getName()).isEqualTo("managed")));
}
@ -94,14 +87,14 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests { @@ -94,14 +87,14 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests {
@Test
void shouldNotRegisterAnnotationProxyIfNotNeeded() {
process(SampleMethodMetaAnnotatedBean.class);
RuntimeHints runtimeHints = this.generationContext.getRuntimeHints();
RuntimeHints runtimeHints = this.runtimeHints;
assertThat(runtimeHints.proxies().jdkProxies()).isEmpty();
}
@Test
void shouldRegisterAnnotationProxy() {
process(SampleMethodMetaAnnotatedBeanWithAlias.class);
RuntimeHints runtimeHints = this.generationContext.getRuntimeHints();
RuntimeHints runtimeHints = this.runtimeHints;
assertThat(RuntimeHintsPredicates.proxies().forInterfaces(
SampleInvoker.class, SynthesizedAnnotation.class)).accepts(runtimeHints);
}
@ -109,10 +102,10 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests { @@ -109,10 +102,10 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests {
@Test
void shouldProcessAnnotationOnInterface() {
process(SampleMethodAnnotatedBeanWithInterface.class);
assertThat(this.generationContext.getRuntimeHints().reflection().getTypeHint(SampleInterface.class))
assertThat(this.runtimeHints.reflection().getTypeHint(SampleInterface.class))
.satisfies(typeHint -> assertThat(typeHint.methods()).singleElement()
.satisfies(methodHint -> assertThat(methodHint.getName()).isEqualTo("managed")));
assertThat(this.generationContext.getRuntimeHints().reflection().getTypeHint(SampleMethodAnnotatedBeanWithInterface.class))
assertThat(this.runtimeHints.reflection().getTypeHint(SampleMethodAnnotatedBeanWithInterface.class))
.satisfies(typeHint -> assertThat(typeHint.methods()).singleElement()
.satisfies(methodHint -> assertThat(methodHint.getName()).isEqualTo("managed")));
}
@ -120,25 +113,16 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests { @@ -120,25 +113,16 @@ class ReflectiveProcessorBeanRegistrationAotProcessorTests {
@Test
void shouldProcessAnnotationOnInheritedClass() {
process(SampleMethodAnnotatedBeanWithInheritance.class);
assertThat(this.generationContext.getRuntimeHints().reflection().getTypeHint(SampleInheritedClass.class))
assertThat(this.runtimeHints.reflection().getTypeHint(SampleInheritedClass.class))
.satisfies(typeHint -> assertThat(typeHint.methods()).singleElement()
.satisfies(methodHint -> assertThat(methodHint.getName()).isEqualTo("managed")));
assertThat(this.generationContext.getRuntimeHints().reflection().getTypeHint(SampleMethodAnnotatedBeanWithInheritance.class))
assertThat(this.runtimeHints.reflection().getTypeHint(SampleMethodAnnotatedBeanWithInheritance.class))
.satisfies(typeHint -> assertThat(typeHint.methods()).singleElement()
.satisfies(methodHint -> assertThat(methodHint.getName()).isEqualTo("managed")));
}
@Nullable
private BeanRegistrationAotContribution createContribution(Class<?> beanClass) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition(beanClass.getName(), new RootBeanDefinition(beanClass));
return this.processor.processAheadOfTime(RegisteredBean.of(beanFactory, beanClass.getName()));
}
private void process(Class<?> beanClass) {
BeanRegistrationAotContribution contribution = createContribution(beanClass);
assertThat(contribution).isNotNull();
contribution.applyTo(this.generationContext, mock(BeanRegistrationCode.class));
this.registrar.registerRuntimeHints(this.runtimeHints, beanClass);
}
@Reflective
Loading…
Cancel
Save