Honor ProtocolResolvers in GenericApplicationContext

When the ProtocolResolver SPI was introduced in Spring Framework 4.3,
support for protocol resolvers was added in DefaultResourceLoader's
getResource() implementation; however, GenericApplicationContext's
overridden getResource() implementation was not updated accordingly.

Prior to this commit, if a GenericApplicationContext was configured
with a custom ResourceLoader, registered protocol resolvers were
ignored.

This commit ensures that protocol resolvers are honored in
GenericApplicationContext even if a custom ResourceLoader is used.

Closes gh-28703
This commit is contained in:
Sam Brannen
2022-06-27 18:00:29 +02:00
parent a970516080
commit 9868c28c73
3 changed files with 78 additions and 7 deletions

View File

@@ -24,15 +24,28 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.FileSystemResourceLoader;
import org.springframework.core.io.FileUrlResource;
import org.springframework.core.io.ProtocolResolver;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.metrics.jfr.FlightRecorderApplicationStartup;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.InstanceOfAssertFactories.type;
/**
* Tests for {@link GenericApplicationContext}.
*
* @author Juergen Hoeller
* @author Chris Beams
* @author Sam Brannen
*/
class GenericApplicationContextTests {
@@ -209,6 +222,39 @@ class GenericApplicationContextTests {
assertThat(context.getBeanFactory().getApplicationStartup()).isEqualTo(applicationStartup);
}
@Test
void getResourceWithDefaultResourceLoader() {
assertGetResourceSemantics(null, ClassPathResource.class);
}
@Test
void getResourceWithCustomResourceLoader() {
assertGetResourceSemantics(new FileSystemResourceLoader(), FileSystemResource.class);
}
private void assertGetResourceSemantics(ResourceLoader resourceLoader, Class<? extends Resource> defaultResouceType) {
if (resourceLoader != null) {
context.setResourceLoader(resourceLoader);
}
String pingLocation = "ping:foo";
String fileLocation = "file:foo";
Resource resource = context.getResource(pingLocation);
assertThat(resource).isInstanceOf(defaultResouceType);
resource = context.getResource(fileLocation);
assertThat(resource).isInstanceOf(FileUrlResource.class);
context.addProtocolResolver(new PingPongProtocolResolver());
resource = context.getResource(pingLocation);
assertThat(resource).asInstanceOf(type(ByteArrayResource.class))
.extracting(bar -> new String(bar.getByteArray(), UTF_8))
.isEqualTo("pong:foo");
resource = context.getResource(fileLocation);
assertThat(resource).isInstanceOf(FileUrlResource.class);
}
static class BeanA {
@@ -236,4 +282,15 @@ class GenericApplicationContextTests {
static class BeanC {}
static class PingPongProtocolResolver implements ProtocolResolver {
@Override
public Resource resolve(String location, ResourceLoader resourceLoader) {
if (location.startsWith("ping:")) {
return new ByteArrayResource(("pong:" + location.substring(5)).getBytes(UTF_8));
}
return null;
}
}
}