老生谈spring(三):初步了解Resource

老生谈spring(三):初步了解Resource

1、接着看上一节的loadBeanDefinitions,这个方法的前几行都是构建beanDefinitionReader,最后一行则是调用loadBeanDefinitions进行xml的解析和注册,下面重点看这个方法。

	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
		initBeanDefinitionReader(beanDefinitionReader);
		loadBeanDefinitions(beanDefinitionReader);
	}

2、其实loadBeanDefinitions主要就是调用XmlBeanDefinitionReader的loadBeanDefinitions方法,加载xml之前会先通过getConfigLocations去获取我们的xml路径

	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

	protected String[] getConfigLocations() {
		return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());
	}

3、至于configLocations的值是怎么来的,我们先看回main方法在new ClassPathXmlApplicationContext时把xml给传了进去。然后在构造方法里调用setConfigLocations,把xml给设置到configLocations

public class XmlApplication {
    public static void main(String[] args) {
        //通过指定xml加载上下文
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
       //启动容器
        context.refresh();
        //从容器中获取A的bean
        A bean = context.getBean(A.class);
        System.out.println(bean.toString());
    }
}

public class ClassPathXmlApplicationContext{
    //构造方法
	public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
		//调用重载的构造方法
		this(new String[] {configLocation}, true, null);
	}
	
	//重载的构造方法
	public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {

		super(parent);
		//把xml设置到configLocations
		setConfigLocations(configLocations);
		if (refresh) {
			refresh();
		}
	}

  //父类方法,把locations设置到configLocations
	public void setConfigLocations(@Nullable String... locations) {
		if (locations != null) {
			Assert.noNullElements(locations, "Config locations must not be null");
			this.configLocations = new String[locations.length];
			for (int i = 0; i < locations.length; i++) {
				this.configLocations[i] = resolvePath(locations[i]).trim();
			}
		}
		else {
			this.configLocations = null;
		}
	}
}

4、XmlBeanDefinitionReader的loadBeanDefinitions方法也是个重载方法,通过遍历locations,最终会调用到下面的loadBeanDefinitions方法。这个方法虽然有点长,但其实就是用resourceLoader解析location得到Resource或者Resource数组,那什么是Resource呢?

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
		}

		if (resourceLoader instanceof ResourcePatternResolver) {
			try {
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				int count = loadBeanDefinitions(resources);
				if (actualResources != null) {
					Collections.addAll(actualResources, resources);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
				}
				return count;
			}
			catch (IOException ex) {
				throw new BeanDefinitionStoreException(
						"Could not resolve bean definition resource pattern [" + location + "]", ex);
			}
		}
		else {
			Resource resource = resourceLoader.getResource(location);
			int count = loadBeanDefinitions(resource);
			if (actualResources != null) {
				actualResources.add(resource);
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
			}
			return count;
		}
	}

5、Resource其实就是spring对一些资源文件的一个统一定义,我们知道能通过它获取到文件流供我们操作就可以了。

public interface Resource extends InputStreamSource {
    boolean exists();

    default boolean isReadable() {
        return this.exists();
    }

    default boolean isOpen() {
        return false;
    }

    default boolean isFile() {
        return false;
    }

    URL getURL() throws IOException;

    URI getURI() throws IOException;

    File getFile() throws IOException;

    default ReadableByteChannel readableChannel() throws IOException {
        return Channels.newChannel(this.getInputStream());
    }

    long contentLength() throws IOException;

    long lastModified() throws IOException;

    Resource createRelative(String var1) throws IOException;

    @Nullable
    String getFilename();

    String getDescription();
}

6、结语:本节主要讲了在new ClassPathXmlApplicationContext时会把指定的xml赋值给configLocations,然后在refresh创建beanfactory时构建一个XmlBeanDefinitionReader,这个reader在执行loadBeanDefinitions方法时会遍历configLocations,然后在加载前会把这些location封装成Resource对象。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值