Spring 中对于如classpath: 这类的解析在哪里进行?

今天遇到一个问题,在Spring中声明的自定义Bean中需要注入 一个配置文件 xxx.xml,想用 SpringBean中配置文件注入的方式如:classpath:xxx-ibatis.xml.

查看了spring 对 ibatis 支持中的 SqlMapClientFactoryBean,发现其configLocation 属性其实是个Resource 接口,尝试直接实例化了实现Resource接口的 ClassPathResource、FileSystemResource 等都无法取得正确的文件路径.

那Spring 对 classpath: 的解析在哪里进行?
在spring 配置文件中对SqlMapClientFactoryBean configLocation 属赋的值又是组装成哪个Resource实现类传入?

仅有的 5 分 求解!!! :cry:

:o 以哪个Resource实现类传入 会不会跟 启动了哪个 ApplicationContext 有关...

Spring getBean的时候,在构造BeanWrapperImpl时候会注册PropertyEditor,代码如下:
AbstractAutowireCapableBeanFactory类中的方法:
[code="java"]
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
try {
Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
BeanWrapper bw = new BeanWrapperImpl(beanInstance);
initBeanWrapper(bw);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
}
}
[/code]
在调用上述方法initBeanWrapper(bw);时,initBeanWrapper方法代码如下(该方法在AbstractBeanFactory中):
[code="java"]
protected void initBeanWrapper(BeanWrapper bw) {
registerCustomEditors(bw);
}
[/code]
registerCustomEditors(bw);代码如下:
[code="java"]
protected void registerCustomEditors(PropertyEditorRegistry registry) {
PropertyEditorRegistrySupport registrySupport =
(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
if (registrySupport != null) {
registrySupport.useConfigValueEditors();
}
if (!this.propertyEditorRegistrars.isEmpty()) {
for (Iterator it = this.propertyEditorRegistrars.iterator(); it.hasNext();) {
PropertyEditorRegistrar registrar = (PropertyEditorRegistrar) it.next();
try {
registrar.registerCustomEditors(registry);
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
if (isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
"] failed because it tried to obtain currently created bean '" + ex.getBeanName() +
"': " + ex.getMessage());
}
onSuppressedException(ex);
continue;
}
}
throw ex;
}
}
}
if (!this.customEditors.isEmpty()) {
for (Iterator it = this.customEditors.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Class requiredType = (Class) entry.getKey();
Object value = entry.getValue();
if (value instanceof PropertyEditor) {
PropertyEditor editor = (PropertyEditor) value;
// Register the editor as shared instance, if possible,
// to make it clear that it might be used concurrently.
if (registrySupport != null) {
registrySupport.registerSharedEditor(requiredType, editor);
}
else {
registry.registerCustomEditor(requiredType, editor);
}
}
else if (value instanceof Class) {
Class editorClass = (Class) value;
registry.registerCustomEditor(requiredType, (PropertyEditor) BeanUtils.instantiateClass(editorClass));
}
else {
throw new IllegalStateException("Illegal custom editor value type: " + value.getClass().getName());
}
}
}
}
[/code]
在上述方法中registrar.registerCustomEditors(registry);调用的是ResourceEditorRegistrar的registerCustomEditors方法,该方法代码如下:
[code="java"]
public void registerCustomEditors(PropertyEditorRegistry registry) {
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader);
registry.registerCustomEditor(Resource.class, baseEditor);
registry.registerCustomEditor(InputStream.class, new InputStreamEditor(baseEditor));
registry.registerCustomEditor(File.class, new FileEditor(baseEditor));
registry.registerCustomEditor(URL.class, new URLEditor(baseEditor));

    ClassLoader classLoader = this.resourceLoader.getClassLoader();
    registry.registerCustomEditor(Class.class, new ClassEditor(classLoader));
    registry.registerCustomEditor(URI.class, new URIEditor(classLoader));

    if (this.resourceLoader instanceof ResourcePatternResolver) {
        registry.registerCustomEditor(Resource[].class,
                new ResourceArrayPropertyEditor((ResourcePatternResolver) this.resourceLoader));
    }
}

[/code]
从上面可以看出对于Resource、Resource[]类型的属性,PropertyEditor分别为ResourceEditor、ResourceArrayPropertyEditor,所以在自己定义的Test类中的属性locations、location是由上面这两个PropertyEditor解析完成的。
而ResourceEditor、ResourceArrayPropertyEditor解析真正用到的是AbstractApplicationContext中的PathMatchingResourcePatternResolver类,所以真正的解析类是PathMatchingResourcePatternResolver

javabean:
[code="java"]
package test;
import org.springframework.core.io.Resource;
public class Test {

private Resource[] locations;
private Resource location;
public Resource[] getLocations() {
    return locations;
}
public void setLocations(Resource[] locations) {
    this.locations = locations;
}
public Resource getLocation() {
    return location;
}
public void setLocation(Resource location) {
    this.location = location;
}

}
[/code]
配置Bean:
[code="xml"]



classpath:test/database.properties



classpath:test/database.properties


[/code]
通过Spring就可以获得test.Test的对象了,其中该对象的locations,location已经被Spring实例成了Resource[]、Resource对象了