zoukankan      html  css  js  c++  java
  • @value

     

     

     通过name来获取bean对象。

     

     这一点eclipse就没有intelliJ好,拉到方法内部上面就不现实方法名了,这里是上面调用的方法的内部。

     

     

    处理内部属性:

     然后就在这里抛出异常了:

     我们打个debug看看:

     

     因为上面这个是循环处理,所以我们一直等到:

    不为空:

     我们进入下面的方法里看看:

     不过貌似这个和我们哪个异常没有关系:

    一不小心按跳过了。。。

    我们继续吧:

    也不是这个:

     但是我们跟着走一遍没错的,然后在循环到报错的看就更清楚了:

    这个跟上个不一样,这个是方法:

     

     这个类挺有意思:

     我们先来看看是哪个方法有注入需求:

     下面这个应该就是核心方法了:

    我们进入看看:

     

    几组判断后进入下面方法:

     

     

    return (isLazy(descriptor) ? buildLazyResolutionProxy(descriptor, beanName) : null);

    一个很简单的判断:

    没看清跳出来了:

     又是一个非常大的方法,这就是spring。

    跳出吧,我们继续我们的找异常之旅:

    过了几十个,终于找到你了:

     这个是个属性注入,@value嘛:

     

    然后我们进入下一行代码:

    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);

    接着调用:DefaultListableBeanFacotory的方法doResolveDependency

        @Override
        public Object resolveDependency(DependencyDescriptor descriptor, String beanName,
                Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
    
            descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
            if (descriptor.getDependencyType().equals(javaUtilOptionalClass)) {
                return new OptionalDependencyFactory().createOptionalDependency(descriptor, beanName);
            }
            else if (ObjectFactory.class == descriptor.getDependencyType()) {
                return new DependencyObjectFactory(descriptor, beanName);
            }
            else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
                return new DependencyProviderFactory().createDependencyProvider(descriptor, beanName);
            }
            else {
                Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, beanName);
                if (result == null) {
                    result = doResolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter);
                }
                return result;
            }
        }
    
        public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
                Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
    
            Class<?> type = descriptor.getDependencyType();
         //获取注解@value的值 Object value
    = getAutowireCandidateResolver().getSuggestedValue(descriptor); if (value != null) { if (value instanceof String) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } if (type.isArray()) { Class<?> componentType = type.getComponentType(); DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor); targetDesc.increaseNestingLevel(); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, targetDesc); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(componentType, "array of " + componentType.getName(), descriptor); } return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); Object result = converter.convertIfNecessary(matchingBeans.values(), type); if (getDependencyComparator() != null && result instanceof Object[]) { Arrays.sort((Object[]) result, adaptDependencyComparator(matchingBeans)); } return result; } else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { Class<?> elementType = descriptor.getCollectionType(); if (elementType == null) { if (descriptor.isRequired()) { throw new FatalBeanException("No element type declared for collection [" + type.getName() + "]"); } return null; } DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor); targetDesc.increaseNestingLevel(); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, targetDesc); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(elementType, "collection of " + elementType.getName(), descriptor); } return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); Object result = converter.convertIfNecessary(matchingBeans.values(), type); if (getDependencyComparator() != null && result instanceof List) { Collections.sort((List<?>) result, adaptDependencyComparator(matchingBeans)); } return result; } else if (Map.class.isAssignableFrom(type) && type.isInterface()) { Class<?> keyType = descriptor.getMapKeyType(); if (String.class != keyType) { if (descriptor.isRequired()) { throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() + "] must be [java.lang.String]"); } return null; } Class<?> valueType = descriptor.getMapValueType(); if (valueType == null) { if (descriptor.isRequired()) { throw new FatalBeanException("No value type declared for map [" + type.getName() + "]"); } return null; } DependencyDescriptor targetDesc = new DependencyDescriptor(descriptor); targetDesc.increaseNestingLevel(); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, targetDesc); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(valueType, "map with value type " + valueType.getName(), descriptor); } return null; } if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } return matchingBeans; } else { Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { if (descriptor.isRequired()) { raiseNoSuchBeanDefinitionException(type, "", descriptor); } return null; } if (matchingBeans.size() > 1) { String primaryBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (primaryBeanName == null) { throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet()); } if (autowiredBeanNames != null) { autowiredBeanNames.add(primaryBeanName); } return matchingBeans.get(primaryBeanName); } // We have exactly one match. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); if (autowiredBeanNames != null) { autowiredBeanNames.add(entry.getKey()); } return entry.getValue(); } }

    所以我怀疑在上面的地方开始处理@value的值,这里关系到后面的只是${env.isdev}还是true

    ========

    Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);

    可能有很多annotations吧

    然后就到了find..

     

    注意这是的value值已经是“${env.isDev}”了。

    所以我们分析完这个===中的内容了。

    ========

    我们由上面标黄的代码进入:

      //org.springframework.beans.TypeConverterDelegate
    /** * Convert the value to the specified required type. * @param newValue the proposed new value * @param requiredType the type we must convert to * (or {@code null} if not known, for example in case of a collection element) * @param methodParam the method parameter that is the target of the conversion * (may be {@code null}) * @return the new value, possibly the result of type conversion * @throws IllegalArgumentException if type conversion failed */ public <T> T convertIfNecessary(Object newValue, Class<T> requiredType, MethodParameter methodParam) throws IllegalArgumentException { return convertIfNecessary(null, null, newValue, requiredType, (methodParam != null ? new TypeDescriptor(methodParam) : TypeDescriptor.valueOf(requiredType))); }

    里面只有一个方法:

        /**
         * Convert the value to the required type (if necessary from a String),
         * for the specified property.
         * @param propertyName name of the property
         * @param oldValue the previous value, if available (may be {@code null})
         * @param newValue the proposed new value
         * @param requiredType the type we must convert to
         * (or {@code null} if not known, for example in case of a collection element)
         * @param typeDescriptor the descriptor for the target property or field
         * @return the new value, possibly the result of type conversion
         * @throws IllegalArgumentException if type conversion failed
         */
        @SuppressWarnings("unchecked")
        public <T> T convertIfNecessary(String propertyName, Object oldValue, Object newValue,
                Class<T> requiredType, TypeDescriptor typeDescriptor) throws IllegalArgumentException {
    
            // Custom editor for this type?
            PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);
    
            ConversionFailedException conversionAttemptEx = null;
    
            // No custom editor but custom ConversionService specified?
            ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
            if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
                TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
                if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
                    try {
                        return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
                    }
                    catch (ConversionFailedException ex) {
                        // fallback to default conversion logic below
                        conversionAttemptEx = ex;
                    }
                }
            }
        //根据debug直接进入了下面这个判断
            Object convertedValue = newValue;
    
            // Value not of required type?
            if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {
                if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
                        convertedValue instanceof String) {
                    TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
                    if (elementTypeDesc != null && Enum.class.isAssignableFrom(elementTypeDesc.getType())) {
                        convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
                    }
                }
                if (editor == null) {
                    editor = findDefaultEditor(requiredType);
                }
                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 == requiredType) {
                        return (T) convertedValue;
                    }
                    else 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 == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
                        // We can stringify any primitive value...
                        return (T) convertedValue.toString();
                    }
                    else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
                        if (conversionAttemptEx == 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;
                    }
                    else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
                        convertedValue = NumberUtils.convertNumberToTargetClass(
                                (Number) convertedValue, (Class<Number>) requiredType);
                        standardConversion = true;
                    }
                }
                else {
                    // convertedValue == null
                    if (javaUtilOptionalEmpty != null && requiredType.equals(javaUtilOptionalEmpty.getClass())) {
                        convertedValue = javaUtilOptionalEmpty;
                    }
                }
    
                if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
                    if (conversionAttemptEx != null) {
                        // Original exception from former ConversionService call above...
                        throw conversionAttemptEx;
                    }
                    else if (conversionService != null) {
                        // ConversionService not tried before, probably custom editor found
                        // but editor couldn't produce the required type...
                        TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
                        if (conversionService.canConvert(sourceTypeDesc, typeDescriptor)) {
                            return (T) conversionService.convert(newValue, sourceTypeDesc, typeDescriptor);
                        }
                    }
    
                    // 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 (conversionAttemptEx != null) {
                if (editor == null && !standardConversion && requiredType != null && Object.class != requiredType) {
                    throw conversionAttemptEx;
                }
                logger.debug("Original ConversionService attempt failed - ignored since " +
                        "PropertyEditor based conversion eventually succeeded", conversionAttemptEx);
            }
    
            return (T) convertedValue;
        }

    注意上面的红箭头,我们需要适配的类型是Bloolean类型。

    这里的convertedvalue是一个string对象。

    继续:

     进入第二个判断:

    if (requiredType != null && !requiredType.isArray() && convertedValue instanceof String[])

    很显然"${env.isDev}"不是一个string[]类型。

    最终进入第三组判断,这次对了:

     由最开始的异常跟踪我们知道,就是在这里抛的异常了。

    Object org.springframework.beans.TypeConverterDelegate.doConvertTextValue(Object oldValue, String newTextValue, PropertyEditor editor)

     三个参数oldValue, newTextValue, editor的值分别是,null,${env.isDev},org.springframework.beans.propertyeditors.CustomBooleanEditor@7c1447b5

     

    就是这里了

     

     最后没有一个匹配上的就爆异常了。

     所以我怀疑那里的参数是不对的。

    我现在这里打个端点,方便等会直接到这里查看:

  • 相关阅读:
    每天一道LeetCode--141.Linked List Cycle(链表环问题)
    每天一道LeetCode--119.Pascal's Triangle II(杨辉三角)
    每天一道LeetCode--118. Pascal's Triangle(杨辉三角)
    CF1277D Let's Play the Words?
    CF1281B Azamon Web Services
    CF1197D Yet Another Subarray Problem
    CF1237D Balanced Playlist
    CF1239A Ivan the Fool and the Probability Theory
    CF1223D Sequence Sorting
    CF1228D Complete Tripartite
  • 原文地址:https://www.cnblogs.com/guazi/p/6698654.html
Copyright © 2011-2022 走看看