当前位置:   article > 正文

Spring源码-资源访问员Resource接口(理论)?!_create a new classpathresource for classloader usa

create a new classpathresource for classloader usage.

前言: 刚刚开始探索Spring源码的小学生. 记录自己的每一段发现.

1. 初识Resource

Spring中最简单的用法, Spring和bean的配合使用. Spring像是一个大水桶, 而bean像是里面的水.
首先定义bean:

public class MyTestBean {
    private String testStr = "testStr";

    public String getTestStr() {
        return testStr;
    }

    public void setTestStr(String testStr) {
        this.testStr = testStr;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

和所有的类一样, 没有什么不同.
接着定义配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="myTestBean" class="bean.MyTestBean"/>
</beans>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

已经完成了Spring的简单用法, 可以写测试代码了:

	@Test
    public void testSimpleLoad(){
        BeanFactory bf = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
        MyTestBean bean = (MyTestBean) bf.getBean("myTestBean");
        assertEquals("testStr", bean.getTestStr());
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

主要研究对象浮出水面: 它是什么? 帮我们做了什么?

new ClassPathResource("spring-config.xml");
  • 1

2.Resource的身世

首先, 唯一的线索是ClassPathResource, 它和Resource有什么联系?:
ClassPathResource的身世
通过ClassPathResource找到了Resource的线索, 继续挖掘Resource的身世:
Resource类图

Resource:

Resource: Interface for a resource descriptor that abstracts from the actual
type of underlying resource, such as a file or class path resource.[一个资源描述的接口, 从底层资源的实际类型抽象出来, 例如文件或者类路径资源.]

Resource的关键实现类或接口:

WriteableResource: Extended interface for a resource that supports writing to it.[为接口扩展了可以写入资源的支持.]
ContextResource: Extended interface for a resource that is loaded from an enclosing ‘context’.[为接口扩展了从上下文加载资源.]

EncodedResource: Holder that combines a Resource descriptor with a specific encoding or Charset to be used for reading from the resource.[将资源描述符与用于读取资源的特定编码或字符集组合在一起的持有者.]

AbstractResource: Convenience base class for Resource implementations, pre-implementing typical behavior.[Resource实现的便利基类]

AbstractResource的关键子类:

DescriptiveResource: Simple Resource implementation that holds a resource description but does not point to an actually readable resource.[简单的Resource实现, 掌握资源描述, 但是不能指向实际的可读资源.]

BeanDefinitionResource: Descriptive Resource wrapper for a BeanDefinition.[BeanDefinition的描述性资源包装.]

ByteArrayResource: Resource implementation for a given byte array.[给定数组的Resource实现.]

AbstractFileResolvingResource: Abstract base class for resources which resolve URLs into File references.[将URL解析为文件饮用的抽象基类.]

AbstractFileResolvingResource的关键子类:

UrlResource: Resource implementation for URL locators.[URL定位器的Resource实现.]

ServletContextResource: Resource implementation for ServletContext resources, interpreting relative paths within the web application root directory.[ServletContext资源的Resource实现, 解释在web应用的root文件夹下的相对路径.]

ClassPathResource: Resource implementation for class path resources. Uses either a given ClassLoader or a given Class for loading resource.[类路径资源的Resource实现, 使用给定的类加载器或给定的类加载资源.]

通过上面的对比, 发现Resource接口实则为了增强JDK中的URL类或File类, 在JDK中, 他们单独存在, 并且缺少从类路径加载资源(ClassPathResource)和从Web容器的上下文中获取资源(ServletContextResource)的类. 所以Spring设计了Resource接口, 用于集百家之长, 并且还补充了其不足.

回到开始的代码

new ClassPathResource("spring-config.xml");
  • 1

通过上面得知, ClassPathResource是类路径资源的Resource实现, 将会通过类加载器或者类来加载资源. 首先来看它的构造方法:

/**
	 * Create a new {@code ClassPathResource} for {@code ClassLoader} usage.
	 * A leading slash will be removed, as the ClassLoader resource access
	 * methods will not accept it.
	 * <p>The thread context class loader will be used for
	 * loading the resource.
	 * @param path the absolute path within the class path
	 * @see java.lang.ClassLoader#getResourceAsStream(String)
	 * @see org.springframework.util.ClassUtils#getDefaultClassLoader()
	 */
	public ClassPathResource(String path) {
		this(path, (ClassLoader) null);
	}
	public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
		Assert.notNull(path, "Path must not be null");
		String pathToUse = StringUtils.cleanPath(path);
		if (pathToUse.startsWith("/")) {
			pathToUse = pathToUse.substring(1);
		}
		this.path = pathToUse;
		this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

首先看官方解释: 为ClassLoader创建一个新的ClassPathResource使用. 将删除一个前倒斜杠, 由于ClassLoader资源入口方法将不会接受它. 逐句分析一下, 断言判断path不能为空. 创建一个pathToUse变量存储将path中的所有"“转为”/", 如果path是以"/“开头的, 那么截取掉开头的”/", 将自身的path赋值为pathToUse, 如果参数中的classLoader不为空的话, 赋值为此参数的classPath, 如果为空的话赋值为ClassUtils.getDefaultClassLoader(). 这其中出现了两个问题, 首先什么是ClassLoader? 然后ClassUtils.getDefaultClassLoader()获得的默认类加载器是什么?[ClassLoader内容过长, 单独文章记录]

直到这里, new ClassPathResource(“spring-config.xml”);这段代码终于执行完成, 可以继续往下进行了:

        BeanFactory bf = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
  • 1

new XmlBeanFactory(Resource); 继续进行.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/66380
推荐阅读
相关标签
  

闽ICP备14008679号