Spring Framework的IOC容器实现(五)(大结局)

这里通过使用BeanDefinitionResolver来对BeanDefinition进行解析,然后注入到property中。下面到BeanDefinitionValueResolver中看一下解析过程,以对Bean reference进行解析为例

/*** Resolve a reference to another bean in the factory.* class BeanDefinitionValueResolver*/private Object resolveReference(Object argName, RuntimeBeanReference ref) {try {// 从RuntimeBeanReference取得reference名字,这个RuntimeBeanReference是在载入BeanDefinition// 时根据配置生成的String refName = ref.getBeanName();refName = String.valueOf(evaluate(refName));// 如果ref是在双亲IOC容器中,那就到双亲IOC容器中去取if (ref.isToParent()) {if (this.beanFactory.getParentBeanFactory() == null) {throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName,”Can’t resolve reference to bean ‘” + refName +”‘ in parent factory: no parent factory available”);}return this.beanFactory.getParentBeanFactory().getBean(refName);}{Object bean = this.beanFactory.getBean(refName);this.beanFactory.registerDependentBean(refName, this.beanName);return bean;}}catch (BeansException ex) {throw new BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName,”Cannot resolve reference to bean ‘” + ref.getBeanName() + “‘ while setting ” + argName, ex);}}

下面看看其他类型属性进行注入的例子,比如array和List

/*** For each element in the managed array, resolve reference if necessary.*/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;}/*** For each element in the managed list, resolve reference if necessary.*/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;}

这两种属性的注入都调用了resolveValueIfNecessary,这个方法包含了所有对注入类型的处理,下面看下里面的具体实现:

/*** Given a PropertyValue, return a value, resolving any references to other* beans in the factory if necessary. The value could be:* <li>A BeanDefinition, which leads to the creation of a corresponding* new bean instance. Singleton flags and names of such “inner beans”* are always ignored: Inner beans are anonymous prototypes.* <li>A RuntimeBeanReference, which must be resolved.* <li>A ManagedList. This is a special collection that may contain* RuntimeBeanReferences or Collections that will need to be resolved.* <li>A ManagedSet. May also contain RuntimeBeanReferences or* Collections that will need to be resolved.* <li>A ManagedMap. In this case the value may be a RuntimeBeanReference* or Collection that will need to be resolved.* <li>An ordinary object or {@code null}, in which case it’s left alone.* @param argName the name of the argument that the value is defined for* @param value the value object to resolve* @return the resolved object*/public Object resolveValueIfNecessary(Object argName, Object value) {(value instanceof RuntimeBeanReference) {RuntimeBeanReference ref = (RuntimeBeanReference) value;return resolveReference(argName, ref);}else if (value instanceof RuntimeBeanNameReference) {String refName = ((RuntimeBeanNameReference) value).getBeanName();refName = String.valueOf(evaluate(refName));if (!this.beanFactory.containsBean(refName)) {throw new BeanDefinitionStoreException(“Invalid bean name ‘” + refName + “‘ in bean reference for ” + argName);}return refName;}else if (value instanceof BeanDefinitionHolder) {// Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());}else if (value instanceof BeanDefinition) {// Resolve plain BeanDefinition, without contained name: use dummy name.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) {// May need to resolve contained runtime references.ManagedArray array = (ManagedArray) value;Class<?> elementType = array.resolvedElementType;if (elementType == null) {String elementTypeName = array.getElementTypeName();if (StringUtils.hasText(elementTypeName)) {try {elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());array.resolvedElementType = elementType;}catch (Throwable ex) {BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName,”Error resolving array type for ” + argName, ex);}}else {elementType = Object.class;}}return resolveManagedArray(argName, (List<?>) value, elementType);}else if (value instanceof ManagedList) {// May need to resolve contained runtime references.return resolveManagedList(argName, (List<?>) value);}else if (value instanceof ManagedSet) {// May need to resolve contained runtime references.return resolveManagedSet(argName, (Set<?>) value);}else if (value instanceof ManagedMap) {// May need to resolve contained runtime references.return resolveManagedMap(argName, (Map<?, ?>) value);}else if (value instanceof 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);}return copy;}else if (value instanceof TypedStringValue) {// Convert value to target type here.TypedStringValue typedStringValue = (TypedStringValue) value;Object valueObject = evaluate(typedStringValue);try {Class<?> resolvedTargetType = resolveTargetType(typedStringValue);if (resolvedTargetType != null) {return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);}else {return valueObject;}}catch (Throwable ex) {BeanCreationException(this.beanDefinition.getResourceDescription(), this.beanName,”Error converting typed String value for ” + argName, ex);}}else {return evaluate(value);}}『 不可能 』只存在於蠢人的字典里

Spring Framework的IOC容器实现(五)(大结局)

相关文章:

你感兴趣的文章:

标签云: