Browse Source

Add ifPresent utility methods on RuntimeHints

This commit adds a utility method to register a type for reflection if
it is available on the classpath. It also adds a method to register a
resource pattern if a given location is available.

Closes gh-28617
pull/28631/head
Stephane Nicoll 3 years ago
parent
commit
d6d4b98780
  1. 17
      spring-core/src/main/java/org/springframework/aot/hint/ReflectionHints.java
  2. 18
      spring-core/src/main/java/org/springframework/aot/hint/ResourceHints.java
  3. 19
      spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java
  4. 19
      spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java

17
spring-core/src/main/java/org/springframework/aot/hint/ReflectionHints.java

@ -30,6 +30,7 @@ import java.util.stream.Stream; @@ -30,6 +30,7 @@ import java.util.stream.Stream;
import org.springframework.aot.hint.TypeHint.Builder;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
* Gather the need for reflection at runtime.
@ -95,6 +96,22 @@ public class ReflectionHints { @@ -95,6 +96,22 @@ public class ReflectionHints {
return registerType(TypeReference.of(type), typeHint);
}
/**
* Register or customize reflection hints for the specified type if it
* is available using the specified {@link ClassLoader}.
* @param classLoader the classloader to use to check if the type is present
* @param typeName the type to customize
* @param typeHint a builder to further customize hints for that type
* @return {@code this}, to facilitate method chaining
*/
public ReflectionHints registerTypeIfPresent(@Nullable ClassLoader classLoader,
String typeName, Consumer<TypeHint.Builder> typeHint) {
if (ClassUtils.isPresent(typeName, classLoader)) {
registerType(TypeReference.of(typeName), typeHint);
}
return this;
}
/**
* Register or customize reflection hints for the types defined by the
* specified list of {@link TypeReference type references}. The specified

18
spring-core/src/main/java/org/springframework/aot/hint/ResourceHints.java

@ -65,6 +65,24 @@ public class ResourceHints { @@ -65,6 +65,24 @@ public class ResourceHints {
return this.resourceBundleHints.stream();
}
/**
* Register a pattern if the given {@code location} is available on the
* classpath. This delegates to {@link ClassLoader#getResource(String)}
* which validates directories as well. The location is not included in
* the hint.
* @param classLoader the classloader to use
* @param location a '/'-separated path name that should exist
* @param resourceHint a builder to customize the resource pattern
* @return {@code this}, to facilitate method chaining
*/
public ResourceHints registerPatternIfPresent(@Nullable ClassLoader classLoader, String location, Consumer<ResourcePatternHints.Builder> resourceHint) {
ClassLoader classLoaderToUse = (classLoader != null) ? classLoader : getClass().getClassLoader();
if (classLoaderToUse.getResource(location) != null) {
registerPattern(resourceHint);
}
return this;
}
/**
* Register that the resources matching the specified pattern should be
* made available at runtime.

19
spring-core/src/test/java/org/springframework/aot/hint/ReflectionHintsTests.java

@ -27,6 +27,8 @@ import org.springframework.lang.Nullable; @@ -27,6 +27,8 @@ import org.springframework.lang.Nullable;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyNoInteractions;
/**
* Tests for {@link ReflectionHints}.
@ -45,6 +47,23 @@ class ReflectionHintsTests { @@ -45,6 +47,23 @@ class ReflectionHintsTests {
typeWithMemberCategories(String.class, MemberCategory.DECLARED_FIELDS));
}
@Test
void registerTypeIfPresentRegisterExistingClass() {
this.reflectionHints.registerTypeIfPresent(null, String.class.getName(),
hint -> hint.withMembers(MemberCategory.DECLARED_FIELDS));
assertThat(this.reflectionHints.typeHints()).singleElement().satisfies(
typeWithMemberCategories(String.class, MemberCategory.DECLARED_FIELDS));
}
@Test
@SuppressWarnings("unchecked")
void registerTypeIfPresentIgnoreMissingClass() {
Consumer<TypeHint.Builder> hintBuilder = mock(Consumer.class);
this.reflectionHints.registerTypeIfPresent(null, "com.example.DoesNotExist", hintBuilder);
assertThat(this.reflectionHints.typeHints()).isEmpty();
verifyNoInteractions(hintBuilder);
}
@Test
void getTypeUsingType() {
this.reflectionHints.registerType(TypeReference.of(String.class),

19
spring-core/src/test/java/org/springframework/aot/hint/ResourceHintsTests.java

@ -26,6 +26,8 @@ import org.junit.jupiter.api.Test; @@ -26,6 +26,8 @@ import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.ResourceHintsTests.Nested.Inner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyNoInteractions;
/**
* Tests for {@link ResourceHints}.
@ -91,6 +93,23 @@ class ResourceHintsTests { @@ -91,6 +93,23 @@ class ResourceHintsTests {
List.of("com/example/to-ignore.properties")));
}
@Test
void registerIfPresentRegisterExistingLocation() {
this.resourceHints.registerPatternIfPresent(null, "META-INF/",
resourceHint -> resourceHint.includes("com/example/*.properties"));
assertThat(this.resourceHints.resourcePatterns()).singleElement().satisfies(
patternOf("com/example/*.properties"));
}
@Test
@SuppressWarnings("unchecked")
void registerIfPresentIgnoreMissingLocation() {
Consumer<ResourcePatternHints.Builder> hintBuilder = mock(Consumer.class);
this.resourceHints.registerPatternIfPresent(null, "location/does-not-exist/", hintBuilder);
assertThat(this.resourceHints.resourcePatterns()).isEmpty();
verifyNoInteractions(hintBuilder);
}
@Test
void registerResourceBundle() {
this.resourceHints.registerResourceBundle("com.example.message");

Loading…
Cancel
Save