2021-07-02阅读小笔记:Spring ioc 之资源扫描

1、SpringFramework 的资源模型是什么?都有哪几种类型?

关于资源加载,SpringFramework没有直接使用JDK的那一套:ClassLoader 的 getResource 和 getResourceAsStream 的方法,而是重新造了一套。

当然了,从源码中分析,其实最底层是使用了JDK的那一套 + 自定义。

SpringFramework 的资源模型,我们可以看从 InputStreamResource 的继承关系看。
在这里插入图片描述

SpringFramework的资源模型中,最上层的是 InputStreamSource,它非常简单,只有一个接口,就是返回输入流

public interface InputStreamSource {
    InputStream getInputStream() throws IOException;
}

而它有一个默认实现类:

  • EncodedResource,这个实现类支持对资源进行编码,里面组合了一个Resource resource,证明它本身不是加载资源的。

还有间接两个子接口:

  • ContextResource
  • WritableResource:支持对资源进行写操作。

2、SpringFramework 默认可以加载的资源都有哪些?顺序分别是什么?

默认加载的资源

Java 原生可以从下面三个地方加载文件:

  • 借助 ClassLoader 加载类路径下的资源
  • 借助 File 加载文件系统中的资源
  • 借助 URL 和不同的协议加载本地 / 网络上的资源

SpringFrameword 也是从这三个地方提供了不同的实现,详情可见 DefaultResourceLoader。

因为我们知道,ApplicationContext 在 BeanFactory 的基础上了扩展了很多特性,其中一个就是资源加载,提供的是「ResourceLoader」接口,而默认实现是 DefaultResourceLoader 类;我们也可以看到 ApplicationContext 的默认实现类 AbstractApplicationContext 也是继承了 DefaultResourceLoader。

那么我们可以从 DefaultResourceLoader 中是怎么对 Java 原生加载文件的方式提供了实现:

@Override
public Resource getResource(String location) {
	Assert.notNull(location, "Location must not be null");
    // 遍历所有 ProtocolResolver,SpringFramewrok或我们可利用此做自定义资源扫描,只需要实现ProtocolResolver接口,再利用 DefaultResourceLoader 的 addProtocolResolver 方法传入到 DefaultResourceLoader 的 protocolResolvers 列表中。
	for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
		Resource resource = protocolResolver.resolve(location, this);
		if (resource != null) {
			return resource;
		}
	}
    // 最后还是利用 ClassPathResource 获取类路径下的文件
	if (location.startsWith("/")) {
		return getResourceByPath(location);
	}
	// classpath: 前缀,利用 ClaspathResource 获取类路径下的文件
	else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
		return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
	}
	else {
		try {
			// Try to parse the location as a URL...
			URL url = new URL(location);
			// 根据判断利用 File 或 URL 获取
			return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
		}
		catch (MalformedURLException ex) {
			// No URL -> resolve as resource path.
			return getResourceByPath(location);
		}
	}
}

/**
 * ClassPathResource that explicitly expresses a context-relative path
 * through implementing the ContextResource interface.
 */
protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {

	public ClassPathContextResource(String path, @Nullable ClassLoader classLoader) {
		super(path, classLoader);
	}

	@Override
	public String getPathWithinContext() {
		return getPath();
	}

	@Override
	public Resource createRelative(String relativePath) {
		String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath);
		return new ClassPathContextResource(pathToUse, getClassLoader());
	}
}

关于扫描顺序

从上面的 DefaultResourceLoader 的源码就可以看出来了:
protocolResolvers -> classpath -> file -> url。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值