Spring源码追踪1——doGetBean(为什么org.springframework.data.redis.core.RedisTemplate的实例可以注入为ListOperations)

来源:互联网 发布:java jdk有安卓版的吗 编辑:程序博客网 时间:2024/06/05 09:02

类org.springframework.beans.factory.support.AbstractBeanFactory
方法T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)

这里requiredType是获取的实例要转换成的类型,转换通过org.springframework.beans.TypeConverter进行。

复制代码
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {    try {        return getTypeConverter().convertIfNecessary(bean, requiredType);    }    catch (TypeMismatchException ex) {        if (logger.isDebugEnabled()) {            logger.debug("Failed to convert bean '" + name + "' to required type [" +                    ClassUtils.getQualifiedName(requiredType) + "]", ex);        }        throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());    }}
复制代码

 

类org.springframework.beans.TypeConverterDelegate

TypeConverter调用java.beans.PropertyEditor。

复制代码
public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,        Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {    Object convertedValue = newValue;    // Custom editor for this type?    PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);    ConversionFailedException firstAttemptEx = null;    // No custom editor but custom ConversionService specified?    ConversionService conversionService = this.propertyEditorRegistry.getConversionService();    if (editor == null && conversionService != null && convertedValue != null && typeDescriptor != null) {        TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);        TypeDescriptor targetTypeDesc = typeDescriptor;        if (conversionService.canConvert(sourceTypeDesc, targetTypeDesc)) {            try {                return (T) conversionService.convert(convertedValue, sourceTypeDesc, targetTypeDesc);            }            catch (ConversionFailedException ex) {                // fallback to default conversion logic below                firstAttemptEx = ex;            }        }    }    // Value not of required type?    if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {        if (requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) {            TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor();            if (elementType != null && Enum.class.isAssignableFrom(elementType.getType())) {                convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);            }        }        if (editor == null) {            editor = findDefaultEditor(requiredType); // redis进入的是此分支路径        }        convertedValue = doConvertValue(oldValue, convertedValue, requiredType, editor);    }    boolean standardConversion = false;    if (requiredType != null) {        // Try to apply some standard type conversion rules if appropriate.        if (convertedValue != null) {            if (Object.class.equals(requiredType)) {                return (T) convertedValue;            }            if (requiredType.isArray()) {                // Array required -> apply appropriate conversion of elements.                if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {                    convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);                }                return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());            }            else if (convertedValue instanceof Collection) {                // Convert elements to target type, if determined.                convertedValue = convertToTypedCollection(                        (Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);                standardConversion = true;            }            else if (convertedValue instanceof Map) {                // Convert keys and values to respective target type, if determined.                convertedValue = convertToTypedMap(                        (Map<?, ?>) convertedValue, propertyName, requiredType, typeDescriptor);                standardConversion = true;            }            if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {                convertedValue = Array.get(convertedValue, 0);                standardConversion = true;            }            if (String.class.equals(requiredType) && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {                // We can stringify any primitive value...                return (T) convertedValue.toString();            }            else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {                if (firstAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {                    try {                        Constructor<T> strCtor = requiredType.getConstructor(String.class);                        return BeanUtils.instantiateClass(strCtor, convertedValue);                    }                    catch (NoSuchMethodException ex) {                        // proceed with field lookup                        if (logger.isTraceEnabled()) {                            logger.trace("No String constructor found on type [" + requiredType.getName() + "]", ex);                        }                    }                    catch (Exception ex) {                        if (logger.isDebugEnabled()) {                            logger.debug("Construction via String failed for type [" + requiredType.getName() + "]", ex);                        }                    }                }                String trimmedValue = ((String) convertedValue).trim();                if (requiredType.isEnum() && "".equals(trimmedValue)) {                    // It's an empty enum identifier: reset the enum value to null.                    return null;                }                convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);                standardConversion = true;            }        }        if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {            if (firstAttemptEx != null) {                throw firstAttemptEx;            }            // Definitely doesn't match: throw IllegalArgumentException/IllegalStateException            StringBuilder msg = new StringBuilder();            msg.append("Cannot convert value of type [").append(ClassUtils.getDescriptiveType(newValue));            msg.append("] to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]");            if (propertyName != null) {                msg.append(" for property '").append(propertyName).append("'");            }            if (editor != null) {                msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(                        "] returned inappropriate value of type [").append(                        ClassUtils.getDescriptiveType(convertedValue)).append("]");                throw new IllegalArgumentException(msg.toString());            }            else {                msg.append(": no matching editors or conversion strategy found");                throw new IllegalStateException(msg.toString());            }        }    }    if (firstAttemptEx != null) {        if (editor == null && !standardConversion && requiredType != null && !Object.class.equals(requiredType)) {            throw firstAttemptEx;        }        logger.debug("Original ConversionService attempt failed - ignored since " +                "PropertyEditor based conversion eventually succeeded", firstAttemptEx);    }    return (T) convertedValue;}
复制代码

 

类org.springframework.beans.BeanUtils
方法PropertyEditor findEditorByConvention(Class<?> targetType)

spring会自动获取type对应的editor

复制代码
String editorName = targetType.getName() + "Editor";try {    Class<?> editorClass = cl.loadClass(editorName);    if (!PropertyEditor.class.isAssignableFrom(editorClass)) {        if (logger.isWarnEnabled()) {            logger.warn("Editor class [" + editorName +                    "] does not implement [java.beans.PropertyEditor] interface");        }        unknownEditorTypes.put(targetType, Boolean.TRUE);        return null;    }    return (PropertyEditor) instantiateClass(editorClass);}
复制代码

 

例如对org.springframework.data.redis.core.ListOperations则有org.springframework.data.redis.core.ListOperationsEditor

复制代码
class ListOperationsEditor extends PropertyEditorSupport {    public void setValue(Object value) {        if (value instanceof RedisOperations) {            super.setValue(((RedisOperations) value).opsForList());        } else {            throw new java.lang.IllegalArgumentException("Editor supports only conversion of type " + RedisOperations.class);        }    }}
复制代码

 原文:http://www.cnblogs.com/chanedi/p/4135303.html

0 1
原创粉丝点击