Spring源代码分析(5)---propertyEditor(移花接木的自定义属性编辑器)
来源:互联网 发布:newbalance淘宝店 编辑:程序博客网 时间:2024/05/16 12:22
- protected void initBeanWrapper(BeanWrapper bw) {
- for (Iterator it = getCustomEditors().entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry) it.next();
- Class clazz = (Class) entry.getKey();
- PropertyEditor editor = (PropertyEditor) entry.getValue();
- bw.registerCustomEditor(clazz, editor);
- }
- }
如:
- <bean name="ResourceInfo" class="org.corey.ResourceInfo">
- <property name="resource1" value="classpath:test/corey.class"/>
- <property name="resource2" value="classpath:test/corey.class"/>
- </bean>
- <bean id="customEditorConfigurer" class="org.spring.framework.beans.factory.config.CustomEditorConfigurer">
- <property name="custromEditors">
- <map>
- <entry key="org.corey.ResourceInfo">
- <bean class="org.springframework.core.io.ResourceEditor"/>
- </entry>
- </map>
- </property>
- /bean>
在这里,我们看见这个EditorConfigurer实现了我们上一节所说的BeanFactoryPostProcessor接口,那么,在BeanFactory加载类配置文件以前,这个EditorConfigurer到底做了什么呢,我们看一下:
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- if (this.customEditors != null) {
- for (Iterator it = this.customEditors.keySet().iterator(); it.hasNext();) {
- Object key = it.next();
- Class requiredType = null;
- if (key instanceof Class) {
- requiredType = (Class) key;
- }
- else if (key instanceof String) {
- String className = (String) key;
- try {
- requiredType = ClassUtils.forName(className);
- }
- catch (ClassNotFoundException ex) {
- throw new BeanInitializationException(
- "Could not load required type [" + className + "] for custom editor", ex);
- }
- }
- else {
- throw new BeanInitializationException(
- "Invalid key [" + key + "] for custom editor - needs to be Class or String");
- }
- Object value = this.customEditors.get(key);
- if (!(value instanceof PropertyEditor)) {
- throw new BeanInitializationException("Mapped value [" + value + "] for custom editor key [" +
- key + "] is not of required type [" + PropertyEditor.class.getName() + "]");
- }
- beanFactory.registerCustomEditor(requiredType, (PropertyEditor) value);
- }
- }
- }
- }
key是指目标类,如上文中的org.corey.ResourceInfo类,value是指属性编辑器;
那么属性编辑器到底是什么呢,我们首先来看看PropertyEditor接口吧;
public interface PropertyEditor{
public void setAsText();
public String getAsText();
}
他有一个默认实现是:PropertyEditorSupport类,从这个接口的方法,我们可以看出,这个接口可以把一个特定类型的对象序列化成为一个字符串,并且又能够把一个字符串反序列化成为一个对象;
如ResourceEditor:
- public class ResourceEditor extends PropertyEditorSupport {
- private final ResourceLoader resourceLoader;
- public ResourceEditor() {
- this.resourceLoader = new DefaultResourceLoader();
- }
- public ResourceEditor(ResourceLoader resourceLoader) {
- this.resourceLoader = resourceLoader;
- }
- public void setAsText(String text) {
- if (StringUtils.hasText(text)) {
- String locationToUse = resolvePath(text).trim();
- setValue(this.resourceLoader.getResource(locationToUse));
- }
- else {
- setValue(null);
- }
- }
- protected String resolvePath(String path) {
- return SystemPropertyUtils.resolvePlaceholders(path);
- }
- }
transformedBeanName(name);:bean名字转换,比如去掉&,把别名改写位正式的名字等等;
transformedBeanName(name);根据名字拿到这个Beanname对应的BeanDefinition(已介绍);
checkMergedBeanDefinition(mergedBeanDefinition, beanName, requiredType, args);查看这个bean定义是不是抽象的;
createBean(beanName, mergedBeanDefinition, args):正式建立一个实例;
createBean()是在AbstractAutoWireBeanFactory中实现的,在这个里面做了创建实例bean的工作,如下:
*[mergedBeanDefinition.getDependsOn().length]getBean(mergedBeanDefinition.getDependsOn());:循环这个bean所依赖的bean,然后getBean();达到预先createBean();这个被依赖类的作用;
instantiateBean(beanName, mergedBeanDefinition);根据所提供的构造函数,或者默认构造函数,或相应的诸如规则调用构造函数生成实例;
populateBean(beanName, mergedBeanDefinition, instanceWrapper);对属性进行注入;
applyBeanPostProcessorsBeforeInitialization(bean, beanName);调用BeanPostProcessorsBeforeInitialization
invokeInitMethods(beanName, bean, mergedBeanDefinition);调用初始化方法;
applyBeanPostProcessorsAfterInitialization(bean, beanName);;调用BeanPostProcessorsAfterInitialization
我们重点来看下instantiateBean:
- protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mergedBeanDefinition)
- throws BeansException {
- Object beanInstance = getInstantiationStrategy().instantiate(mergedBeanDefinition, beanName, this);
- BeanWrapper bw = new BeanWrapperImpl(beanInstance);
- initBeanWrapper(bw);
- return bw;
- }
- protected void initBeanWrapper(BeanWrapper bw) {
- for (Iterator it = getCustomEditors().entrySet().iterator(); it.hasNext();) {
- Map.Entry entry = (Map.Entry) it.next();
- Class clazz = (Class) entry.getKey();
- PropertyEditor editor = (PropertyEditor) entry.getValue();
- bw.registerCustomEditor(clazz, editor);
- }
- }
populateBean:
- protected void populateBean(String beanName, RootBeanDefinition mergedBeanDefinition, BeanWrapper bw)
- throws BeansException {
- PropertyValues pvs = mergedBeanDefinition.getPropertyValues();
- if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
- mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
- MutablePropertyValues mpvs = new MutablePropertyValues(pvs);
- // Add property values based on autowire by name if applicable.
- if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
- autowireByName(beanName, mergedBeanDefinition, bw, mpvs);
- }
- // Add property values based on autowire by type if applicable.
- if (mergedBeanDefinition.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
- autowireByType(beanName, mergedBeanDefinition, bw, mpvs);
- }
- pvs = mpvs;
- }
- checkDependencies(beanName, mergedBeanDefinition, bw, pvs);
- applyPropertyValues(beanName, mergedBeanDefinition, bw, pvs);
- }
applyPropertyValues:
- private void applyPropertyValues(
- String beanName, RootBeanDefinition mergedBeanDefinition, BeanWrapper bw, PropertyValues pvs)
- throws BeansException {
- if (pvs == null) {
- return;
- }
- BeanDefinitionValueResolver valueResolver =
- new BeanDefinitionValueResolver(this, beanName, mergedBeanDefinition);
- // Create a deep copy, resolving any references for values.
- MutablePropertyValues deepCopy = new MutablePropertyValues();
- PropertyValue[] pvArray = pvs.getPropertyValues();
- for (int i = 0; i < pvArray.length; i++) {
- PropertyValue pv = pvArray[i];
- Object resolvedValue =
- valueResolver.resolveValueIfNecessary("bean property '" + pv.getName() + "'", pv.getValue());
- deepCopy.addPropertyValue(pvArray[i].getName(), resolvedValue);
- }
- // Set our (possibly massaged) deep copy.
- try {
- // Synchronize if custom editors are registered.
- // Necessary because PropertyEditors are not thread-safe.
- if (!getCustomEditors().isEmpty()) {
- synchronized (this) {
- bw.setPropertyValues(deepCopy);
- }
- }
- else {
- bw.setPropertyValues(deepCopy);
- }
- }
- catch (BeansException ex) {
- // Improve the message by showing the context.
- throw new BeanCreationException(
- mergedBeanDefinition.getResourceDescription(), beanName, "Error setting property values", ex);
- }
- }
- protected Object doTypeConversionIfNecessary(String propertyName, String fullPropertyName,
- Object oldValue, Object newValue, Class requiredType) throws TypeMismatchException {
- Object convertedValue = newValue;
- // Custom editor for this type?
- PropertyEditor pe = findCustomEditor(requiredType, fullPropertyName);
- // Value not of required type?
- if (pe != null ||
- (requiredType != null &&
- (requiredType.isArray() || !requiredType.isInstance(convertedValue)))) {
- if (requiredType != null) {
- if (pe == null) {
- // No custom editor -> check BeanWrapperImpl's default editors.
- pe = (PropertyEditor) getDefaultEditor(requiredType);
- if (pe == null) {
- // No BeanWrapper default editor -> check standard JavaBean editors.
- pe = PropertyEditorManager.findEditor(requiredType);
- }
- }
- }
- if (pe != null && !(convertedValue instanceof String)) {
- // Not a String -> use PropertyEditor's setValue.
- // With standard PropertyEditors, this will return the very same object;
- // we just want to allow special PropertyEditors to override setValue
- // for type conversion from non-String values to the required type.
- try {
- pe.setValue(convertedValue);
- Object newConvertedValue = pe.getValue();
- if (newConvertedValue != convertedValue) {
- convertedValue = newConvertedValue;
- // Reset PropertyEditor: It already did a proper conversion.
- // Don't use it again for a setAsText call.
- pe = null;
- }
- }
- catch (IllegalArgumentException ex) {
- throw new TypeMismatchException(
- createPropertyChangeEvent(fullPropertyName, oldValue, newValue), requiredType, ex);
- }
- }
- if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[]) {
- // Convert String array to a comma-separated String.
- // Only applies if no PropertyEditor converted the String array before.
- // The CSV String will be passed into a PropertyEditor's setAsText method, if any.
- if (logger.isDebugEnabled()) {
- logger.debug("Converting String array to comma-delimited String [" + convertedValue + "]");
- }
- convertedValue = StringUtils.arrayToCommaDelimitedString((String[]) convertedValue);
- }
- if (pe != null && convertedValue instanceof String) {
- // Use PropertyEditor's setAsText in case of a String value.
- if (logger.isDebugEnabled()) {
- logger.debug("Converting String to [" + requiredType + "] using property editor [" + pe + "]");
- }
- try {
- //转换的点在这里,你可以清晰的看见;;;;;
- pe.setValue(oldValue);
- pe.setAsText((String) convertedValue);
- convertedValue = pe.getValue();
- }
- catch (IllegalArgumentException ex) {
- throw new TypeMismatchException(
- createPropertyChangeEvent(fullPropertyName, oldValue, newValue), requiredType, ex);
- }
- }
- if (requiredType != null) {
- // Array required -> apply appropriate conversion of elements.
- if (requiredType.isArray()) {
- Class componentType = requiredType.getComponentType();
- if (convertedValue instanceof Collection) {
- // Convert Collection elements to array elements.
- Collection coll = (Collection) convertedValue;
- Object result = Array.newInstance(componentType, coll.size());
- int i = 0;
- for (Iterator it = coll.iterator(); it.hasNext(); i++) {
- Object value = doTypeConversionIfNecessary(
- propertyName, propertyName + PROPERTY_KEY_PREFIX + i + PROPERTY_KEY_SUFFIX,
- null, it.next(), componentType);
- Array.set(result, i, value);
- }
- return result;
- }
- else if (convertedValue != null && convertedValue.getClass().isArray()) {
- // Convert Collection elements to array elements.
- int arrayLength = Array.getLength(convertedValue);
- Object result = Array.newInstance(componentType, arrayLength);
- for (int i = 0; i < arrayLength; i++) {
- Object value = doTypeConversionIfNecessary(
- propertyName, propertyName + PROPERTY_KEY_PREFIX + i + PROPERTY_KEY_SUFFIX,
- null, Array.get(convertedValue, i), componentType);
- Array.set(result, i, value);
- }
- return result;
- }
- else if (convertedValue != null) {
- // A plain value: convert it to an array with a single component.
- Object result = Array.newInstance(componentType, 1);
- Object value = doTypeConversionIfNecessary(
- propertyName, propertyName + PROPERTY_KEY_PREFIX + 0 + PROPERTY_KEY_SUFFIX,
- null, convertedValue, componentType);
- Array.set(result, 0, value);
- return result;
- }
- }
- // If the resulting value definitely doesn't match the required type,
- // try field lookup as fallback. If no matching field found,
- // throw explicit TypeMismatchException with full context information.
- if (convertedValue != null && !requiredType.isPrimitive() &&
- !requiredType.isInstance(convertedValue)) {
- // In case of String value, try to find matching field (for JDK 1.5
- // enum or custom enum with values defined as static fields).
- if (convertedValue instanceof String) {
- try {
- Field enumField = requiredType.getField((String) convertedValue);
- return enumField.get(null);
- }
- catch (Exception ex) {
- if (logger.isDebugEnabled()) {
- logger.debug("Field [" + convertedValue + "] isn't an enum value", ex);
- }
- }
- }
- // Definitely doesn't match: throw TypeMismatchException.
- throw new TypeMismatchException(
- createPropertyChangeEvent(fullPropertyName, oldValue, newValue), requiredType);
- }
- }
- }
- return convertedValue;
- }
- Spring源代码分析(5)---propertyEditor(移花接木的自定义属性编辑器)
- Spring IOC 自定义属性编辑器PropertyEditor
- 属性编辑器PropertyEditor-->Spring IoC
- Spring的自定义PropertyEditor
- spring配置自定义的PropertyEditor
- Spring PropertyEditor分析
- spring 强大的PropertyEditor
- 探秘Spring的PropertyEditor
- 关于在Spring中注册自定义的PropertyEditor
- 关于在Spring中注册自定义的PropertyEditor
- Spring自定义属性编辑器
- Spring自定义属性编辑器
- spring自定义属性编辑器
- Spring自定义属性编辑器
- Spring-----自定义属性编辑器
- spring自定义属性编辑器的配置
- spring中自定义属性编辑器的实现
- spring的自定义属性编辑器CustomEditorConfigurer
- [.NET]ADO.NET调用存储过程
- PHP实现HTML标签转换
- 欢迎光顾梦之翼飞翔软件博客
- 知道的越多,不知道的越多!
- 一句话总结奥运
- Spring源代码分析(5)---propertyEditor(移花接木的自定义属性编辑器)
- 编程中空格的使用
- 开始J2ME学习
- MSSQL2005 鸡肋提权啊~~-_-
- 网线制作
- Solaris2.4 多线程编程指南3--使用同步对象编程
- 关于gridview的表格线
- Solaris2.4 多线程编程指南4--操作系统编程
- InfoGlue:如何下载和安装