AbstractRefreshableWebApplicationContext
下面的子类都是和web相关了。所以就和ServletContext相关嘛~~~
// @since 1.1.3 public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext implements ConfigurableWebApplicationContext, ThemeSource { ... @Override protected Resource getResourceByPath(String path) { Assert.state(this.servletContext != null, "No ServletContext available"); return new ServletContextResource(this.servletContext, path); } // ServletContextResourcePatternResolver是PathMatchingResourcePatternResolver的子类 @Override protected ResourcePatternResolver getResourcePatternResolver() { return new ServletContextResourcePatternResolver(this); } ... }
XmlWebApplicationContext
他没有自己的实现,但我们可议简单的回味一下它的类
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { /** Default config location for the root context */ public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml"; /** Default prefix for building a config location for a namespace */ public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/"; /** Default suffix for building a config location for a namespace */ public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml"; ... }
AnnotationConfigWebApplicationContext
它是注解驱动的,所以也就没有必要冲洗方法喽 @since 3.0
GenericApplicationContext
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry { ... // 它重写一个逻辑都是:加入调用者自己指定了resourceLoader,那就以调用者为准 @Override public Resource getResource(String location) { if (this.resourceLoader != null) { return this.resourceLoader.getResource(location); } return super.getResource(location); } @Override public Resource[] getResources(String locationPattern) throws IOException { if (this.resourceLoader instanceof ResourcePatternResolver) { return ((ResourcePatternResolver) this.resourceLoader).getResources(locationPattern); } return super.getResources(locationPattern); } ... }
如图的几个子类。除了带web的重写了一下(使用ServletContextResource和ServletContextResourcePatternResolver),其余子类都没有重写的必要~~~~
子接口 ResourcePatternResolver 解析
上面已经介绍了ResourceLoader的实现,那么接下来针对于子接口进一步讨论。其实它使用得反而更加的广泛,也更加的强大。从名字中可以看出,它支持Pattern,支持正则的模式匹配,非常的强大~~~
用于解析资源文件的策略接口,其特殊的地方在于,它应该提供带有*号这种通配符的资源路径。 此接口是ResourceLoader接口的拓展接口。
// @since 1.0.2 显然它出现的时机晚于ResourceLoader接口 public interface ResourcePatternResolver extends ResourceLoader { // 与ResourceLoader中classpath不同的地方在于,此前缀会在所有的JAR包的根目录下搜索指定文件。 非常的强大 String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; // 返回指定路径下所有的资源对象。 // 返回的对象数组有Set的语义,也就是说,`对于同一个资源,只返回一个资源对象` Resource[] getResources(String locationPattern) throws IOException; }
先来个Demo,简单的感受下classpath*的威力:
public static void main(String[] args) throws IOException { ResourceLoader resourceLoader = new DefaultResourceLoader(); Resource resource = resourceLoader.getResource("classpath:META-INF/spring.factories"); // 因为`classpath:`只在本工程内查找,所以肯定找不到 spring.factories System.out.println(resource.exists()); //false PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); Resource[] resources = resourcePatternResolver.getResources("classpath*:META-INF/spring.factories"); // 它会去找所有的jar包的类路径开始查找,所以现在是可议找到多个的~~~ System.out.println(resources.length); //2 System.out.println(Arrays.asList(resources)); //[URL [jar:file:/E:/repository/org/springframework/spring-beans/5.0.6.RELEASE/spring-beans-5.0.6.RELEASE.jar!/META-INF/spring.factories], //URL [jar:file:/E:/repository/org/springframework/spring-test/5.0.6.RELEASE/spring-test-5.0.6.RELEASE.jar!/META-INF/spring.factories]] // 还能使用Ant风格进行匹配~~~ 太强大了: resources = resourcePatternResolver.getResources("classpath*:META-INF/*.factories"); System.out.println(resources); // 能匹配上所有了路径下,`META-INF/*.factories`匹配上的所有文件 resources = resourcePatternResolver.getResources("classpath*:com/fsx/**/*.class"); System.out.println(resources.length); //42 相当于把我当前项目所有的类都拿出来了 }