Spring源码:PropertyValues类及属性注入二

2023-11-16

主代码

对Bean属性原始值的解析过程在BeanDefinitionValueResolver类中的resolveValueIfNecessary方法中,BeanDefinitionValueResolver主要是用于将bean定义对象中包含的值解析为应用于目标bean实例的实际值。

public Object resolveValueIfNecessary(Object argName, Object value) {
    if (value instanceof RuntimeBeanReference) {
        // 1. RuntimeBeanReference类型
        RuntimeBeanReference ref = (RuntimeBeanReference) value;
        return resolveReference(argName, ref);
    } else if (value instanceof RuntimeBeanNameReference) {
        // 2. RuntimeBeanNameReference类型
        String refName = ((RuntimeBeanNameReference) value).getBeanName();
        refName = String.valueOf(doEvaluate(refName));
        if (!this.beanFactory.containsBean(refName)) {
            // 抛出异常
        }
        return refName;
    } else if (value instanceof BeanDefinitionHolder) {
        // 3. BeanDefinitionHolder类型
        BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;
        return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());
    } else if (value instanceof BeanDefinition) {
        // 4. BeanDefinition类型
        BeanDefinition bd = (BeanDefinition) value;
        String innerBeanName = "(inner bean)" + BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(bd);
        return resolveInnerBean(argName, innerBeanName, bd);
    } else if (value instanceof ManagedArray) {
        // 5.ManagedArray类型
        ManagedArray array = (ManagedArray) value;
        // 运行时解析的元素类型
        Class<?> elementType = array.resolvedElementType;
        if (elementType == null) {
            String elementTypeName = array.getElementTypeName();
            if (StringUtils.hasText(elementTypeName)) {
                elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());
                array.resolvedElementType = elementType;
            } else {
                elementType = Object.class;
            }
        }
        return resolveManagedArray(argName, (List<?>) value, elementType);
    } else if (value instanceof ManagedList) {
        // 6.ManagedList类型
        return resolveManagedList(argName, (List<?>) value);
    } else if (value instanceof ManagedSet) {
        // 7.ManagedSet类型
        return resolveManagedSet(argName, (Set<?>) value);
    } else if (value instanceof ManagedMap) {
        // 8.ManagedMap类型
        return resolveManagedMap(argName, (Map<?, ?>) value);
    } else if (value instanceof ManagedProperties) {
        // 9.ManagedProperties类型
        Properties original = (Properties) value;
        Properties copy = new Properties();
        for (Map.Entry<Object, Object> propEntry : original.entrySet()) {
            Object propKey = propEntry.getKey();
            Object propValue = propEntry.getValue();
            if (propKey instanceof TypedStringValue) {
                propKey = evaluate((TypedStringValue) propKey);
            }
            if (propValue instanceof TypedStringValue) {
                propValue = evaluate((TypedStringValue) propValue);
            }
            copy.put(propKey, propValue);
        } // for
        return copy;
    } else if (value instanceof TypedStringValue) {
        // 10.TypedStringValue类型
        TypedStringValue typedStringValue = (TypedStringValue) value;
        // 解析value
        Object valueObject = evaluate(typedStringValue);
        // 解析typedStringValue的类型
        Class<?> resolvedTargetType = resolveTargetType(typedStringValue);
        if (resolvedTargetType != null) {
            // 若从typedStringValue内部解析出类型,则使用转换器进行类型转换
            return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);
        } else { 
            // 若没有解析出类型,直接返回
            return valueObject;
        }
    } else {
        // 其他情况
        return evaluate(value);
    }
}
1. RuntimeBeanReference类型
  • 用途

RuntimeBeanReference:当属性值对象是工厂中另一个bean的引用时,使用不可变的占位符类,在运行时进行解析。

<bean class="foo.bar.xxx">
    <property name="referBeanName" ref="otherBeanName" />
</bean>

解析器会依据依赖bean的name创建一个RuntimeBeanReference对像,将这个对像放入BeanDefinition的MutablePropertyValues中,即

reference = new RuntimeBeanReference("otherBeanName");
xxxBeanDefinition.getPropertyValues().addPropertyValue("referBeanName", reference);
  • 转换过程
private Object resolveReference(Object argName, RuntimeBeanReference ref) {
    // 获取该Bean引用名称,如上例“otherBeanName”
    String refName = ref.getBeanName();
    // 若refName是SPEL表达式,需要解析
    refName = String.valueOf(doEvaluate(refName));
    if (ref.isToParent()) {
        // 若显式引用父工厂中的bean
        if (this.beanFactory.getParentBeanFactory() == null) {
            // 抛出异常:显式引用父工厂中的bean但父工厂bean不存在
        }
        return this.beanFactory.getParentBeanFactory().getBean(refName);
    } else {
        // 获取该引用Bean
        Object bean = this.beanFactory.getBean(refName);
        // 注册依赖的Bean(this.beanName依赖refName)
        this.beanFactory.registerDependentBean(refName, this.beanName);
        return bean;
    }
}

private Object doEvaluate(String value) {
    // beanFactory来解析
    return this.beanFactory.evaluateBeanDefinitionString(value, this.beanDefinition);
}

再看AbstractBeanFactory对该表达式的解析,首先会判断是否存在语言解析器,如果存在则调用语言解析器(ExpressionParser)的方法进行解析(应用语言解析器的调用主要是在解析依赖注入bean的时候,以及在完成bean的初始化和属性获取后进行属性填充的时候)。

protected Object evaluateBeanDefinitionString(String value, BeanDefinition beanDefinition){
    if (this.beanExpressionResolver == null) {
        return value;
    }
    // 获取该beanDefinition的Scope(可能为prototype、singleton、request等等)
    Scope scope = (beanDefinition != null ? getRegisteredScope(beanDefinition.getScope()) : null);
    return this.beanExpressionResolver.evaluate(value, new BeanExpressionContext(this, scope));
}
2. RuntimeBeanNameReference类型

代码中直接返回了refName,而非其指向的Bean实例,RuntimeBeanNameReference没有弄明白,可讨论

3. BeanDefinitionHolder类型
  • 用途:

具有名称和别名的bean定义的持有者,可以注册为内部bean的占位符。源码:

public class BeanDefinitionHolder implements BeanMetadataElement {

    private final BeanDefinition beanDefinition;
    private final String beanName;
    @Nullable
    private final String[] aliases;
}
  • 转换过程
private Object resolveInnerBean(Object argName, String innerBeanName, BeanDefinition innerBd) {
    RootBeanDefinition mbd = null;
    // 获取合并BeanDefinition
    mbd = this.beanFactory.getMergedBeanDefinition(innerBeanName, innerBd, this.beanDefinition);

    String actualInnerBeanName = innerBeanName;
    if (mbd.isSingleton()) {
        // 若是单例,则生成唯一的Bean名称(增加计数器直到名称是唯一的)
        actualInnerBeanName = adaptInnerBeanName(innerBeanName);
    }
    // 注册内部bean与包含该bean的bean的关系
    this.beanFactory.registerContainedBean(actualInnerBeanName, this.beanName);

    // 确保内部bean所依赖的bean的初始化
    String[] dependsOn = mbd.getDependsOn();
    if (dependsOn != null) {
        for (String dependsOnBean : dependsOn) {
            this.beanFactory.registerDependentBean(dependsOnBean, actualInnerBeanName);
            this.beanFactory.getBean(dependsOnBean);
        }
    }

    // 开始创建内部bean
    Object innerBean = this.beanFactory.createBean(actualInnerBeanName, mbd, null);
    if (innerBean instanceof FactoryBean) {
        // 若是工厂Bean,调用getObject方法生成Bean,并返回
        boolean synthetic = mbd.isSynthetic();
        return this.beanFactory.getObjectFromFactoryBean((FactoryBean<?>) innerBean, actualInnerBeanName, !synthetic);
    } else {
        return innerBean;
    }
}
4. BeanDefinition类型
  • 用途

匿名bean,就是没有名称(id)的bean,不能被其他bean用名称获取到,只能通过autowire=”byType”方式获取;如果有某个类,不想被其他类通过任何方式获取,只为某个类提供服务,则需要采用内部匿名类,用法如下:

<bean id="myStudent" class="com.hk.spring.di10.Student" autowire="byType">
        <property name="name" value="张三"/>
        <property name="age" value="9"/>
        <property name="school">
            <!-- 内部匿名bean -->
            <bean class="com.hk.spring.di10.School">
            <property name="schloolName" value="红林小学"/>
</bean>
  • 转换过程

代码中可以看出,该内部Bean的名称是自动生成的且唯一的,转换过程类似于BeanDefinitionHolder类型的转换。

5. ManagedArray类型
  • 用途

用于保存托管数组元素的集合类,这些元素可能包括运行时bean引用(要解析为bean对象),源码:

public class ManagedArray extends ManagedList<Object> {
    // 目标数组创建运行时的解析的元素类型
    volatile Class<?> resolvedElementType;
    //......
}

//用于保存托管列表元素的集合类,这些元素可能包括运行时bean引用(要解析为bean对象)
public class ManagedList<E> extends ArrayList<E> implements Mergeable, BeanMetadataElement {
    @Nullable
    private Object source;

    @Nullable
    private String elementTypeName;

    // 该集合是否允许合并另一个集合的元素
    private boolean mergeEnabled;
}
  • 转换过程
private Object resolveManagedArray(Object argName, List<?> ml, Class<?> elementType) {
    Object resolved = Array.newInstance(elementType, ml.size());
    for (int i = 0; i < ml.size(); i++) {
        // 解析并转换每一个元素
        Array.set(resolved, i, resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
    }
    return resolved;
}
6. ManagedList类型
  • 用途

用于保存托管列表元素的集合类,这些元素可能包括运行时bean引用(要解析为bean对象)

  • 转换过程
private List<?> resolveManagedList(Object argName, List<?> ml) {
    List<Object> resolved = new ArrayList<Object>(ml.size());
    for (int i = 0; i < ml.size(); i++) {
        resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
    }
    return resolved;
}
7. ManagedSet类型
  • 用途

用于保存托管Set值的集合类,这些元素可能包括运行时bean引用(要解析为bean对象)

public class ManagedSet<E> extends LinkedHashSet<E> implements Mergeable, BeanMetadataElement {
    private Object source;

    private String elementTypeName;

    private boolean mergeEnabled;
}
  • 转换过程
private Set<?> resolveManagedSet(Object argName, Set<?> ms) {
    Set<Object> resolved = new LinkedHashSet<Object>(ms.size());
    int i = 0;
    for (Object m : ms) {
        resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m));
        i++;
    }
    return resolved;
}
8. ManagedMap类型
  • 用途

用于保存托管map值的集合类,这些元素可能包括运行时bean引用(要解析为bean对象)

public class ManagedMap<K, V> extends LinkedHashMap<K, V> implements Mergeable, BeanMetadataElement {
    private Object source;

    private String keyTypeName;

    private String valueTypeName;

    private boolean mergeEnabled;
}
  • 转换过程
private Map<?, ?> resolveManagedMap(Object argName, Map<?, ?> mm) {
    Map<Object, Object> resolved = new LinkedHashMap<Object, Object>(mm.size());
    for (Map.Entry<?, ?> entry : mm.entrySet()) {
        // 解析key
        Object resolvedKey = resolveValueIfNecessary(argName, entry.getKey());
        // 解析value
        Object resolvedValue = resolveValueIfNecessary(new KeyedArgName(argName, entry.getKey()), entry.getValue());
        resolved.put(resolvedKey, resolvedValue);
    }
    return resolved;
}
9. ManagedProperties类型
  • 用途

spring管理的Properties实例,该实例支持父/子定义的合并。

public class ManagedProperties extends Properties implements Mergeable, BeanMetadataElement {
    private Object source;
    private boolean mergeEnabled;
    //......
}
  • 转换过程
protected Object evaluate(TypedStringValue value) {
    // 若有必要,则使用SPEL解析器进行解析
    Object result = doEvaluate(value.getValue());
    if (!ObjectUtils.nullSafeEquals(result, value.getValue())) {
        // 若解析后的与原来的值不相等,设置该value是动态的
        value.setDynamic();
    }
    return result;
}
10.TypedStringValue类型
  • 用途

类型字符串值的容器。可以添加到bean定义中,以便为字符串值(例如集合元素)显式指定目标类型。

public class TypedStringValue implements BeanMetadataElement {
    @Nullable
    private String value;

    @Nullable
    private volatile Object targetType;

    @Nullable
    private Object source;

    @Nullable
    private String specifiedTypeName;

    private volatile boolean dynamic;
    //......
}
11. 其他情况
protected Object evaluate(Object value) {
    if (value instanceof String) {
        // 字符串(最后会使用SPEL解析器进行解析)
        return doEvaluate((String) value);
    } else if (value instanceof String[]) {
        // 字符串数组
        String[] values = (String[]) value;
        boolean actuallyResolved = false;
        Object[] resolvedValues = new Object[values.length];
        for (int i = 0; i < values.length; i++) {
            String originalValue = values[i];
            // 每一个元素进行解析 
            Object resolvedValue = doEvaluate(originalValue);
            if (resolvedValue != originalValue) {
                actuallyResolved = true;
            }
            resolvedValues[i] = resolvedValue;
        }
        return (actuallyResolved ? resolvedValues : values);
    } else {
        // 即不是字符串,也不是字符数组
        return value;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring源码:PropertyValues类及属性注入二 的相关文章

随机推荐