在Spring的配置中,使用配置类还稍微好理解一点,毕竟直接使用的就是相对应的对象,但是使用XML时就稍稍有点难理解,在XML解析时里面的像这样的子元素
<property name="" value=""/>
value值统统都会转化成String值,我们有时候对应的property对应的类型是int将其转换成int也就罢了,但有时候不是int,而是像Date,Resource,File等等这些类型,他又是怎么转化过去的呢?
比如:
import org.springframework.core.io.Resource;
public class Test {
Resource resource;
public Test(Resource resource){
this.resource=resource;
}
}
这里边有个Resource属性
<bean id="test" class="Helison.Test">
<constructor-arg index="0" value="classpath:resources"/>
</bean>
在XML文件里面将会这么配置,运行完全成功,不报错,为什么呢,value明明是String啊,此时将涉及到PropertyEditor(属性编辑器)以及相关的类了
spring在为bean的相关属性进行赋值的时候,会在其beanFactory里面寻找相对应的属性编辑器,其作用是将解析到的String类型的值转化成我们所需要的其他类型的值,比如Resource,Date等等,因此你需要提供一种映射机制去做这件事;
相关Spring的源码如下:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//关键是这句话
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}
ResourceEditorRegistrar相关源码:
注册相关的PropertyEditor
public void registerCustomEditors(PropertyEditorRegistry registry) {
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
this.doRegisterEditor(registry, Resource.class, baseEditor);
this.doRegisterEditor(registry, ContextResource.class, baseEditor);
this.doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
this.doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
this.doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
if (pathClass != null) {
this.doRegisterEditor(registry, pathClass, new PathEditor(baseEditor));
}
this.doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
this.doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
ClassLoader classLoader = this.resourceLoader.getClassLoader();
this.doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
this.doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
this.doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));
if (this.resourceLoader instanceof ResourcePatternResolver) {
this.doRegisterEditor(registry, Resource[].class, new ResourceArrayPropertyEditor((ResourcePatternResolver)this.resourceLoader, this.propertyResolver));
}
}
上面源码注册已经为我们注册了一些常用的PropertyEditor,像Resource,File,Url等等,but,我们自己注册的那些在哪呢???
继续探索源码,发现:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Iterator var4 = this.getBeanPostProcessors().iterator();
do {
if (!var4.hasNext()) {
return result;
}
BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
} while(result != null);
return result;
}
在进行为beanFactory进行配置后会调用上述方法,而
public class CustomEditorConfigurer implements BeanFactoryPostProcessor, Ordered
CustomEditorConfigurer实现了BeanFactoryPostProcessor(注,BeanFactoryPostProcessor是个很重要的接口)将会被容器发现,并注册
因此我们只需要在配置文件中声明一个CustomEditorConfigurer,就好了,如下:
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<bean class="Helison.DatePropertyEditor"/>
</list>
</property>
</bean>
而
public class DatePropertyEditor implements PropertyEditorRegistrar {
@Override
public void registerCustomEditors(PropertyEditorRegistry propertyEditorRegistry) {
propertyEditorRegistry.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
}
}
此时就可以放心的进行使用了
7208

被折叠的 条评论
为什么被折叠?



