Polishing
This commit is contained in:
parent
1f0a35bacc
commit
eb91d21ada
|
@ -38,6 +38,7 @@ class SchedulerFactoryBeanRuntimeHints implements RuntimeHintsRegistrar {
|
|||
|
||||
private final ReflectiveRuntimeHintsRegistrar reflectiveRegistrar = new ReflectiveRuntimeHintsRegistrar();
|
||||
|
||||
|
||||
@Override
|
||||
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||
if (!ClassUtils.isPresent(SCHEDULER_FACTORY_CLASS_NAME, classLoader)) {
|
||||
|
@ -53,4 +54,5 @@ class SchedulerFactoryBeanRuntimeHints implements RuntimeHintsRegistrar {
|
|||
private void typeHint(Builder typeHint) {
|
||||
typeHint.withMembers(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS).onReachableType(SchedulerFactoryBean.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
|||
* should be processed.
|
||||
*
|
||||
* <p>Unlike declaring {@link RuntimeHintsRegistrar} using
|
||||
* {@code spring/aot.factories}, this annotation allows for more flexible
|
||||
* {@code META-INF/spring/aot.factories}, this annotation allows for more flexible
|
||||
* registration where it is only processed if the annotated component or bean
|
||||
* method is actually registered in the bean factory. To illustrate this
|
||||
* behavior, consider the following example:
|
||||
|
@ -47,19 +47,24 @@ import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
|||
*
|
||||
* }</pre>
|
||||
*
|
||||
* If the configuration class above is processed, {@code MyHints} will be
|
||||
* contributed only if {@code MyCondition} matches. If it does not, and
|
||||
* therefore {@code MyService} is not defined as a bean, the hints will
|
||||
* <p>If the configuration class above is processed, {@code MyHints} will be
|
||||
* contributed only if {@code MyCondition} matches. If the condition does not
|
||||
* match, {@code MyService} will not be defined as a bean and the hints will
|
||||
* not be processed either.
|
||||
*
|
||||
* <p>If several components refer to the same {@link RuntimeHintsRegistrar}
|
||||
* implementation, it is invoked only once for a given bean factory
|
||||
* processing.
|
||||
* <p>{@code @ImportRuntimeHints} can also be applied to any test class that uses
|
||||
* the <em>Spring TestContext Framework</em> to load an {@code ApplicationContext}.
|
||||
*
|
||||
* <p>If several components or test classes refer to the same {@link RuntimeHintsRegistrar}
|
||||
* implementation, the registrar will only be invoked once for the given bean factory
|
||||
* processing or test suite.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Stephane Nicoll
|
||||
* @since 6.0
|
||||
* @see org.springframework.aot.hint.RuntimeHints
|
||||
* @see org.springframework.aot.hint.annotation.Reflective
|
||||
* @see org.springframework.aot.hint.annotation.RegisterReflectionForBinding
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.springframework.core.annotation.AliasFor;
|
|||
*
|
||||
* <p>When present, either directly or as a meta-annotation, this annotation
|
||||
* triggers the configured {@linkplain ReflectiveProcessor processors} against
|
||||
* the annotated element. By default, a reflection hint is added on the
|
||||
* the annotated element. By default, a reflection hint is registered for the
|
||||
* annotated element so that it can be discovered and invoked if necessary.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
|
@ -37,6 +37,7 @@ import org.springframework.core.annotation.AliasFor;
|
|||
* @since 6.0
|
||||
* @see SimpleReflectiveProcessor
|
||||
* @see ReflectiveRuntimeHintsRegistrar
|
||||
* @see RegisterReflectionForBinding @RegisterReflectionForBinding
|
||||
*/
|
||||
@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.CONSTRUCTOR,
|
||||
ElementType.FIELD, ElementType.METHOD })
|
||||
|
|
|
@ -24,8 +24,12 @@ import org.springframework.aot.hint.ReflectionHints;
|
|||
* Process an {@link AnnotatedElement} and register the necessary reflection
|
||||
* hints for it.
|
||||
*
|
||||
* <p>{@code ReflectiveProcessor} implementations are registered via
|
||||
* {@link Reflective#processors() @Reflective(processors = ...)}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 6.0
|
||||
* @see Reflective @Reflective
|
||||
*/
|
||||
public interface ReflectiveProcessor {
|
||||
|
||||
|
|
|
@ -96,12 +96,12 @@ public class ReflectiveRuntimeHintsRegistrar {
|
|||
.stream(Reflective.class)
|
||||
.map(annotation -> annotation.getClassArray("value"))
|
||||
.flatMap(Arrays::stream)
|
||||
.map(type -> (Class<? extends ReflectiveProcessor>) type)
|
||||
.distinct()
|
||||
.map(type -> (Class<? extends ReflectiveProcessor>) type)
|
||||
.map(processorClass -> this.processors.computeIfAbsent(processorClass, this::instantiateClass))
|
||||
.toList();
|
||||
ReflectiveProcessor processorToUse = (processors.size() == 1 ? processors.get(0)
|
||||
: new DelegatingReflectiveProcessor(processors));
|
||||
ReflectiveProcessor processorToUse = (processors.size() == 1 ? processors.get(0) :
|
||||
new DelegatingReflectiveProcessor(processors));
|
||||
return new Entry(element, processorToUse);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,25 +25,24 @@ import java.lang.annotation.Target;
|
|||
import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Indicate that the classes specified in the annotation attributes require some
|
||||
* Indicates that the classes specified in the annotation attributes require some
|
||||
* reflection hints for binding or reflection-based serialization purposes. For each
|
||||
* class specified, hints on constructors, fields, properties, record components,
|
||||
* including types transitively used on properties and record components are registered.
|
||||
* At least one class must be specified in the {@code value} or {@code classes} annotation
|
||||
* attributes.
|
||||
*
|
||||
* <p>The annotated element can be a configuration class, for example:
|
||||
* <p>The annotated element can be a configuration class — for example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Configuration
|
||||
* @RegisterReflectionForBinding({ Foo.class, Bar.class })
|
||||
* public class MyConfig {
|
||||
*
|
||||
* // ...
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The annotated element can also be any Spring bean class, constructor, field, or method.
|
||||
* For example:
|
||||
* <p>The annotated element can be any Spring bean class, constructor, field,
|
||||
* or method — for example:
|
||||
*
|
||||
* <pre class="code">
|
||||
* @Service
|
||||
|
@ -56,9 +55,13 @@ import org.springframework.core.annotation.AliasFor;
|
|||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The annotated element can also be any test class that uses the <em>Spring
|
||||
* TestContext Framework</em> to load an {@code ApplicationContext}.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @since 6.0
|
||||
* @see org.springframework.aot.hint.BindingReflectionHintsRegistrar
|
||||
* @see Reflective @Reflective
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
@ -67,10 +70,7 @@ import org.springframework.core.annotation.AliasFor;
|
|||
public @interface RegisterReflectionForBinding {
|
||||
|
||||
/**
|
||||
* Classes for which reflection hints should be registered.
|
||||
* <p>At least one class must be specified either via {@link #value} or
|
||||
* {@link #classes}.
|
||||
* @see #classes()
|
||||
* Alias for {@link #classes()}.
|
||||
*/
|
||||
@AliasFor("classes")
|
||||
Class<?>[] value() default {};
|
||||
|
|
|
@ -36,9 +36,11 @@ public class RegisterReflectionForBindingProcessor implements ReflectiveProcesso
|
|||
|
||||
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
|
||||
|
||||
|
||||
@Override
|
||||
public void registerReflectionHints(ReflectionHints hints, AnnotatedElement element) {
|
||||
RegisterReflectionForBinding registerReflection = AnnotationUtils.getAnnotation(element, RegisterReflectionForBinding.class);
|
||||
RegisterReflectionForBinding registerReflection =
|
||||
AnnotationUtils.getAnnotation(element, RegisterReflectionForBinding.class);
|
||||
if (registerReflection != null) {
|
||||
Class<?>[] classes = registerReflection.classes();
|
||||
Assert.state(classes.length != 0, () -> "A least one class should be specified in " +
|
||||
|
|
|
@ -34,12 +34,13 @@ import org.springframework.messaging.support.MessageHeaderAccessor;
|
|||
|
||||
/**
|
||||
* {@link ReflectiveProcessor} implementation for {@link MessageMapping}
|
||||
* annotated types. On top of registering reflection hints for invoking
|
||||
* annotated types. In addition to registering reflection hints for invoking
|
||||
* the annotated method, this implementation handles:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Return types.</li>
|
||||
* <li>Parameters identified as potential payload.</li>
|
||||
* <li>{@link Message} parameters.</li>
|
||||
* <li>Return types</li>
|
||||
* <li>Parameters identified as potential payloads</li>
|
||||
* <li>{@link Message} parameters</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
|
@ -49,6 +50,7 @@ class MessageMappingReflectiveProcessor implements ReflectiveProcessor {
|
|||
|
||||
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
|
||||
|
||||
|
||||
@Override
|
||||
public void registerReflectionHints(ReflectionHints hints, AnnotatedElement element) {
|
||||
if (element instanceof Class<?> type) {
|
||||
|
@ -99,6 +101,8 @@ class MessageMappingReflectiveProcessor implements ReflectiveProcessor {
|
|||
@Nullable
|
||||
protected Type getMessageType(MethodParameter parameter) {
|
||||
MethodParameter nestedParameter = parameter.nested();
|
||||
return (nestedParameter.getNestedParameterType() == nestedParameter.getParameterType() ? null : nestedParameter.getNestedParameterType());
|
||||
return (nestedParameter.getNestedParameterType() == nestedParameter.getParameterType() ?
|
||||
null : nestedParameter.getNestedParameterType());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -137,15 +137,20 @@ public class TestContextAotGenerator {
|
|||
mergedConfigMappings.add(mergedConfig, testClass);
|
||||
collectRuntimeHintsRegistrarClasses(testClass, coreRuntimeHintsRegistrarClasses);
|
||||
reflectiveRuntimeHintsRegistrar.registerRuntimeHints(this.runtimeHints, testClass);
|
||||
this.testRuntimeHintsRegistrars.forEach(registrar ->
|
||||
registrar.registerHints(this.runtimeHints, testClass, classLoader));
|
||||
this.testRuntimeHintsRegistrars.forEach(registrar -> {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Processing RuntimeHints contribution from class [%s]"
|
||||
.formatted(registrar.getClass().getCanonicalName()));
|
||||
}
|
||||
registrar.registerHints(this.runtimeHints, testClass, classLoader);
|
||||
});
|
||||
});
|
||||
|
||||
coreRuntimeHintsRegistrarClasses.stream()
|
||||
.map(BeanUtils::instantiateClass)
|
||||
.forEach(registrar -> {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Processing RuntimeHints contribution from test class [%s]"
|
||||
logger.trace("Processing RuntimeHints contribution from class [%s]"
|
||||
.formatted(registrar.getClass().getCanonicalName()));
|
||||
}
|
||||
registrar.registerHints(this.runtimeHints, classLoader);
|
||||
|
|
|
@ -34,6 +34,12 @@ import org.springframework.aot.hint.RuntimeHints;
|
|||
* specific to particular test classes, favor implementing {@code RuntimeHintsRegistrar}
|
||||
* over this API.
|
||||
*
|
||||
* <p>As an alternative to implementing and registering a {@code TestRuntimeHintsRegistrar},
|
||||
* you may choose to annotate a test class with
|
||||
* {@link org.springframework.aot.hint.annotation.Reflective @Reflective},
|
||||
* {@link org.springframework.aot.hint.annotation.RegisterReflectionForBinding @RegisterReflectionForBinding},
|
||||
* or {@link org.springframework.context.annotation.ImportRuntimeHints @ImportRuntimeHints}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.0
|
||||
* @see org.springframework.aot.hint.RuntimeHintsRegistrar
|
||||
|
|
|
@ -33,12 +33,13 @@ import org.springframework.stereotype.Controller;
|
|||
|
||||
/**
|
||||
* {@link ReflectiveProcessor} implementation for {@link Controller} and
|
||||
* controller-specific annotated methods. On top of registering reflection
|
||||
* controller-specific annotated methods. In addition to registering reflection
|
||||
* hints for invoking the annotated method, this implementation handles:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Return types annotated with {@link ResponseBody}.</li>
|
||||
* <li>Parameters annotated with {@link RequestBody}.</li>
|
||||
* <li>{@link HttpEntity} return type and parameters.</li>
|
||||
* <li>Return types annotated with {@link ResponseBody}</li>
|
||||
* <li>Parameters annotated with {@link RequestBody}</li>
|
||||
* <li>{@link HttpEntity} return types and parameters</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
|
@ -49,6 +50,7 @@ class ControllerMappingReflectiveProcessor implements ReflectiveProcessor {
|
|||
|
||||
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
|
||||
|
||||
|
||||
@Override
|
||||
public void registerReflectionHints(ReflectionHints hints, AnnotatedElement element) {
|
||||
if (element instanceof Class<?> type) {
|
||||
|
@ -98,8 +100,8 @@ class ControllerMappingReflectiveProcessor implements ReflectiveProcessor {
|
|||
@Nullable
|
||||
private Type getHttpEntityType(MethodParameter parameter) {
|
||||
MethodParameter nestedParameter = parameter.nested();
|
||||
return (nestedParameter.getNestedParameterType() == nestedParameter.getParameterType()
|
||||
? null : nestedParameter.getNestedParameterType());
|
||||
return (nestedParameter.getNestedParameterType() == nestedParameter.getParameterType() ?
|
||||
null : nestedParameter.getNestedParameterType());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,4 +37,5 @@ class ExceptionHandlerReflectiveProcessor extends ControllerMappingReflectivePro
|
|||
}
|
||||
super.registerReturnTypeHints(hints, returnTypeParameter);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||
|
||||
/**
|
||||
* {@link ReflectiveProcessor} implementation for {@link HttpExchange @HttpExchange}
|
||||
* and annotated methods. On top of registering reflection hints for invoking
|
||||
* annotated methods. In addition to registering reflection hints for invoking
|
||||
* the annotated method, this implementation handles reflection-based
|
||||
* binding for return types and parameters annotated with {@link RequestBody}.
|
||||
*
|
||||
|
@ -40,6 +40,7 @@ class HttpExchangeReflectiveProcessor implements ReflectiveProcessor {
|
|||
|
||||
private final BindingReflectionHintsRegistrar bindingRegistrar = new BindingReflectionHintsRegistrar();
|
||||
|
||||
|
||||
@Override
|
||||
public void registerReflectionHints(ReflectionHints hints, AnnotatedElement element) {
|
||||
if (element instanceof Method method) {
|
||||
|
|
Loading…
Reference in New Issue