⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 beanwrapperimpl.java

📁 spring的源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright 2002-2004 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.beans;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyDescriptor;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.propertyeditors.ByteArrayPropertyEditor;
import org.springframework.beans.propertyeditors.ClassEditor;
import org.springframework.beans.propertyeditors.FileEditor;
import org.springframework.beans.propertyeditors.InputStreamEditor;
import org.springframework.beans.propertyeditors.LocaleEditor;
import org.springframework.beans.propertyeditors.PropertiesEditor;
import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
import org.springframework.beans.propertyeditors.URLEditor;
import org.springframework.util.StringUtils;

/**
 * Default implementation of the BeanWrapper interface that should be sufficient
 * for all normal uses. Caches introspection results for efficiency.
 *
 * <p>Note: This class never tries to load a class by name, as this can pose
 * class loading problems in J2EE applications with multiple deployment modules.
 * The caller is responsible for loading a target class.
 *
 * <p>Note: Auto-registers all default property editors (not the custom ones)
 * in the org.springframework.beans.propertyeditors package.
 * Applications can either use a standard PropertyEditorManager to register a
 * custom editor before using a BeanWrapperImpl instance, or call the instance's
 * registerCustomEditor method to register an editor for the particular instance.
 *
 * <p>BeanWrapperImpl will convert List and array values to the corresponding
 * target arrays, if necessary. Custom property editors that deal with Lists or
 * arrays can be written against a comma delimited String as String arrays are
 * converted in such a format if the array itself is not assignable.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Jean-Pierre Pawlak
 * @since 15 April 2001
 * @version $Id: BeanWrapperImpl.java,v 1.37 2004/04/05 07:17:55 jhoeller Exp $
 * @see #registerCustomEditor
 * @see java.beans.PropertyEditorManager
 * @see org.springframework.beans.propertyeditors.ClassEditor
 * @see org.springframework.beans.propertyeditors.FileEditor
 * @see org.springframework.beans.propertyeditors.LocaleEditor
 * @see org.springframework.beans.propertyeditors.PropertiesEditor
 * @see org.springframework.beans.propertyeditors.StringArrayPropertyEditor
 * @see org.springframework.beans.propertyeditors.URLEditor
 */
public class BeanWrapperImpl implements BeanWrapper {

	/** We'll create a lot of these objects, so we don't want a new logger every time */
	private static final Log logger = LogFactory.getLog(BeanWrapperImpl.class);

	/** Registry for default PropertyEditors */
	private static final Map defaultEditors = new HashMap();

	static {
		// Register default editors in this class, for restricted environments.
		// We're not using the JRE's PropertyEditorManager to avoid potential
		// SecurityExceptions when running in a SecurityManager.
		defaultEditors.put(byte[].class, ByteArrayPropertyEditor.class);
		defaultEditors.put(Class.class, ClassEditor.class);
		defaultEditors.put(File.class, FileEditor.class);
		defaultEditors.put(InputStream.class, InputStreamEditor.class);
		defaultEditors.put(Locale.class, LocaleEditor.class);
		defaultEditors.put(Properties.class, PropertiesEditor.class);
		defaultEditors.put(String[].class, StringArrayPropertyEditor.class);
		defaultEditors.put(URL.class, URLEditor.class);
	}


	//---------------------------------------------------------------------
	// Instance data
	//---------------------------------------------------------------------

	/** The wrapped object */
	private Object object;

	/** The nested path of the object */
	private String nestedPath = "";

	/* Map with cached nested BeanWrappers */
	private Map nestedBeanWrappers;

	/** Map with custom PropertyEditor instances */
	private Map customEditors;

	/**
	 * Cached introspections results for this object, to prevent encountering the cost
	 * of JavaBeans introspection every time.
	 */
	private CachedIntrospectionResults cachedIntrospectionResults;


	//---------------------------------------------------------------------
	// Constructors
	//---------------------------------------------------------------------

	/**
	 * Create new empty BeanWrapperImpl. Wrapped instance needs to be set afterwards.
	 * @see #setWrappedInstance
	 */
	public BeanWrapperImpl() {
	}

	/**
	 * Create new BeanWrapperImpl for the given object.
	 * @param object object wrapped by this BeanWrapper.
	 * @throws BeansException if the object cannot be wrapped by a BeanWrapper
	 */
	public BeanWrapperImpl(Object object) throws BeansException {
		setWrappedInstance(object);
	}

	/**
	 * Create new BeanWrapperImpl for the given object,
	 * registering a nested path that the object is in.
	 * @param object object wrapped by this BeanWrapper.
	 * @param nestedPath the nested path of the object
	 * @throws BeansException if the object cannot be wrapped by a BeanWrapper
	 */
	public BeanWrapperImpl(Object object, String nestedPath) throws BeansException {
		setWrappedInstance(object);
		this.nestedPath = nestedPath;
	}

	/**
	 * Create new BeanWrapperImpl, wrapping a new instance of the specified class.
	 * @param clazz class to instantiate and wrap
	 * @throws BeansException if the class cannot be wrapped by a BeanWrapper
	 */
	public BeanWrapperImpl(Class clazz) throws BeansException {
		setWrappedInstance(BeanUtils.instantiateClass(clazz));
	}


	//---------------------------------------------------------------------
	// Implementation of BeanWrapper
	//---------------------------------------------------------------------

	/**
	 * Switches the target object, replacing the cached introspection results only
	 * if the class of the new object is different to that of the replaced object.
	 * @param object new target
	 * @throws BeansException if the object cannot be changed
	 */
	public void setWrappedInstance(Object object) throws BeansException {
		if (object == null) {
			throw new FatalBeanException("Cannot set BeanWrapperImpl target to a null object");
		}
		this.object = object;
		this.nestedBeanWrappers = null;
		if (this.cachedIntrospectionResults == null ||
		    !this.cachedIntrospectionResults.getBeanClass().equals(object.getClass())) {
			this.cachedIntrospectionResults = CachedIntrospectionResults.forClass(object.getClass());
		}
	}

	public Class getWrappedClass() {
		return object.getClass();
	}

	public Object getWrappedInstance() {
		return object;
	}


	public void registerCustomEditor(Class requiredType, PropertyEditor propertyEditor) {
		registerCustomEditor(requiredType, null, propertyEditor);
	}

	public void registerCustomEditor(Class requiredType, String propertyPath, PropertyEditor propertyEditor) {
		if (propertyPath != null) {
			List bws = getBeanWrappersForPropertyPath(propertyPath);
			for (Iterator it = bws.iterator(); it.hasNext();) {
				BeanWrapperImpl bw = (BeanWrapperImpl) it.next();
				bw.doRegisterCustomEditor(requiredType, getFinalPath(propertyPath), propertyEditor);
			}
		}
		else {
			doRegisterCustomEditor(requiredType, propertyPath, propertyEditor);
		}
	}

	private void doRegisterCustomEditor(Class requiredType, String propertyName, PropertyEditor propertyEditor) {
		if (this.customEditors == null) {
			this.customEditors = new HashMap();
		}
		if (propertyName != null) {
			this.customEditors.put(propertyName, propertyEditor);
		}
		else {
			if (requiredType == null) {
				throw new IllegalArgumentException("No propertyName and no requiredType specified");
			}
			this.customEditors.put(requiredType, propertyEditor);
		}
	}

	public PropertyEditor findCustomEditor(Class requiredType, String propertyPath) {
		if (propertyPath != null) {
			BeanWrapperImpl bw = getBeanWrapperForPropertyPath(propertyPath);
			return bw.doFindCustomEditor(requiredType, getFinalPath(propertyPath));
		}
		else {
			return doFindCustomEditor(requiredType, propertyPath);
		}
	}

	private PropertyEditor doFindCustomEditor(Class requiredType, String propertyName) {
		if (this.customEditors == null) {
			return null;
		}
		if (propertyName != null) {
			// check property-specific editor first
			try {
				PropertyEditor editor = (PropertyEditor) this.customEditors.get(propertyName);
				if (editor == null) {
					int keyIndex = propertyName.indexOf('[');
					if (keyIndex != -1) {
						editor = (PropertyEditor) this.customEditors.get(propertyName.substring(0, keyIndex));
					}
				}
				if (editor != null) {
					return editor;
				}
				else {
					if (requiredType == null) {
						// try property type
						requiredType = getPropertyDescriptor(propertyName).getPropertyType();
					}
				}
			}
			catch (BeansException ex) {
				// probably an indexed or mapped property
				// we need to retrieve the value to determine the type
				requiredType = getPropertyValue(propertyName).getClass();
			}
		}
		// no property-specific editor -> check type-specific editor
		return (PropertyEditor) this.customEditors.get(requiredType);
	}


	/**
	 * Is the property nested? That is, does it contain the nested
	 * property separator (usually ".").
	 * @param path property path
	 * @return boolean is the property nested
	 */
	private boolean isNestedProperty(String path) {
		return path.indexOf(NESTED_PROPERTY_SEPARATOR) != -1;
	}

	/**
	 * Get the last component of the path. Also works if not nested.
	 * @param nestedPath property path we know is nested
	 * @return last component of the path (the property on the target bean)
	 */
	private String getFinalPath(String nestedPath) {
		return nestedPath.substring(nestedPath.lastIndexOf(NESTED_PROPERTY_SEPARATOR) + 1);
	}

	/**
	 * Recursively navigate to return a BeanWrapper for the nested property path.
	 * @param propertyPath property property path, which may be nested
	 * @return a BeanWrapper for the target bean
	 */
	private BeanWrapperImpl getBeanWrapperForPropertyPath(String propertyPath) {
		int pos = propertyPath.indexOf(NESTED_PROPERTY_SEPARATOR);
		// handle nested properties recursively
		if (pos > -1) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -