标准API访问资源
java 提供的标准API中,资源是使用
URI
来标识资源本身,
而如果需要访问资源,则通常使用URL
以及文件IO来完成,
尤其是访问来自网络的资源是,通常会使用URL类。URL类不能方便的访问所有资源,比如无法从
ClassPath
或者
ServletContext
的路径来加载和访问资源。
虽然Java可以自己定义一些URL前缀
,但同时需要安装一个协议处理器
使URL
类支持这个协议,但这样做通常比较复杂。
Spring中资源访问相关的类关系
spirng 使用Resource
接口来抽象资源,接口中定义了一些对资源的操作,该接口提供了更强的资源访问能力。Spring 框架本身大量使用了 Resource 接口来访问底层资源。
Resource
继承了InputStreamSource
接口,使其可以获取资源的底层输入流。
Resource
接口有一些不同的实现类,主要有:
- UrlResource:访问网络资源的实现类。
- ClassPathResource:访问类路径资源。
- FileSystemResource:访问文件系统资源。
- ServletContextResource:访问相对于ServletContext路径下的资源的实现类。
- InputStreamResource:访问输入流资源的实现类。
- ByteArrayResource:访问字节数组资源。
实现了ResourceLoader
接口的类可以获得某个Resource
的实例。ApplicationContext
也是该接口的子接口,因此ApplicationContext
也具有加载资源的能力。
Spring对资源访问的封装是策略模式
的经典实现。
策略模式
这是一篇关于策略模式的博客:http://www.cnblogs.com/java-my-life/archive/2012/05/10/2491891.html
策略模式的UML图:
策略模式封装了算法或者行为的细节到单独的类中,使算法之间可以相互替换,扩展算法的同时不会影响到其他算法,即是开闭原则的体现。
Spring封装资源访问的策略模式
Resource 接口就代表资源访问策略,但具体采用哪种策略实现,Resource 接口并不理会。
客户端程序只和 Resource 接口耦合,并不知道底层采用何种资源访问策略,
这样应用可以在不同的资源访问策略之间自由切换。
通常普通的策略模式中,客户端还是需要指定策略类,即将策略类传入到
Context
对象中,
这样就会把具体的策略类与客户端耦合。Spring中使用了策略
+工厂
的方式实现了客户端和具体策略类的解耦。
ResourceLoader
即是一个Context
也是Factory
,它可以提供Resource
实例。
客户端只需要提供访问资源路径前缀ResourceLoader
就能选择不同的访问策略。
ResourceLoader
的一些子类(即一些Spring容器)也做了一些默认处理,即在未指定路径访问前缀时,
会根据当前不同的ApplicationContext
自动选择访问资源的策略。有时那些具体的策略类(比如:
ClassPathResource
FileSystemResource
)会有一些公共的行为,
这种情况比较好的做法是把这些共有行为方法抽象策略类里面(比如:AbstractResource
),方便复用。
这是上面博客链接中的一个图: