Spring源码解析:Bean的实例化与依赖注入(四)
2012-09-21 15:20
716 查看
在第三部分,我们介绍了BeanDefinition在IOC容器中的注册,本节将介绍Bean的实例化与依赖注入。
Bean的实例化与依赖注入是在用户第一次向IOC容器索要Bean时触发的(例外情况暂不考虑)。每一个BeanFactory都会有一个getBean的方法,现在我们就来看看DefaultListableBeanFactory的getBean方法。
一:getBean方法(DefaultListableBeanFactory)
其实所有的getBean最终都会委托doGetBean来处理的,源码如下:
doGetBean的基本思想是根据BeanDefinition的信息生成Bean,这个方法的思路如下:
(1)如果在单例池中已经存在这个Bean,直接返回
(2)如果当前的BeanFactory中不存在这个Bean的BeanDefinition,那么就依次到这个BeanFactory的父工厂上去取,这里使用递归,直到找到最顶层的BeanFactory.
(3)递归地生成依赖的Bean
(4)根据当前工厂中的BeanDefinition完成Bean的实例化和依赖注入。
根据源码,我们可以看到真正的生成Bean的动作是发生在createBean方法中的,createBean是在DefaultListableBeanFactory的父类AbstractAutowireCapableBeanFactory中实现的,下面我们来看一下createBean的源码.
二:createBean的源码如下
createBean里最核心的操作是doCreateBean,我们跟进doCreateBean里来看看其中的操作:
在这里最核心的操作有两个,一个是createBeanInstance,这个方法主要是用于完成Bean的实例化,可能采用工厂方法,也可能采用构造方法new等,具体的操作根据BeanDefinition中的配置信息。另一个是populateBean方法,这个方法主要完成了依赖注入的功能。
createBean方法源码解析:
在这里我们可以看到,根据BeanDefinition中的配置信息,生成Bean的实例的方式不同,有的采用工厂方法的方式,有的采用带参的构造方法的模式,有的采用无参的构造方法的模式。我们进入instantiateBean中来看看具体的代码。
这里使用配置的实例化策略来完成实例化工作,根据源码我们可以知道使用的CglibSubclassingInstantiationStrategy()来生成bean的代理。
下面,我们继续来看populateBean是如何完成Bean的依赖注入的
我们进入applyPropertyValues来看看Spring是如何真正实现依赖注入的
从这里,我们可以看出真正对属性值进行解析处理注入的实际BeanDefinitionValueResolver的resolveValueIfNecessary方法.
在这里我们可以看到对set,map,list,properties等的解析,具体的动作请进入相关的方法来分析查看,这里不做详述了。
Bean的实例化与依赖注入是在用户第一次向IOC容器索要Bean时触发的(例外情况暂不考虑)。每一个BeanFactory都会有一个getBean的方法,现在我们就来看看DefaultListableBeanFactory的getBean方法。
一:getBean方法(DefaultListableBeanFactory)
public Object getBean(String name) throws BeansException { return getBean(name, null, null); }
其实所有的getBean最终都会委托doGetBean来处理的,源码如下:
/** * Return an instance, which may be shared or independent, of the specified bean. * @param name the name of the bean to retrieve * @param requiredType the required type of the bean to retrieve * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. It is invalid to use a non-null args value in any other case. * @param typeCheckOnly whether the instance is obtained for a type check, * not for actual use * @return an instance of the bean * @throws BeansException if the bean could not be created */ protected Object doGetBean( final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean = null; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (args != null) { // Delegation to parent with explicit args. return parentBeanFactory.getBean(nameToLookup, args); } else { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName); } final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (int i = 0; i < dependsOn.length; i++) { String dependsOnBean = dependsOn[i]; getBean(dependsOnBean); registerDependentBean(dependsOnBean, beanName); } } // Create bean instance. if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); final Scope scope = (Scope) this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, new ObjectFactory() { public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return bean; }
doGetBean的基本思想是根据BeanDefinition的信息生成Bean,这个方法的思路如下:
(1)如果在单例池中已经存在这个Bean,直接返回
(2)如果当前的BeanFactory中不存在这个Bean的BeanDefinition,那么就依次到这个BeanFactory的父工厂上去取,这里使用递归,直到找到最顶层的BeanFactory.
(3)递归地生成依赖的Bean
(4)根据当前工厂中的BeanDefinition完成Bean的实例化和依赖注入。
根据源码,我们可以看到真正的生成Bean的动作是发生在createBean方法中的,createBean是在DefaultListableBeanFactory的父类AbstractAutowireCapableBeanFactory中实现的,下面我们来看一下createBean的源码.
二:createBean的源码如下
/** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */ protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { AccessControlContext acc = AccessController.getContext(); return AccessController.doPrivileged(new PrivilegedAction() { public Object run() { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } // Make sure bean class is actually resolved at this point. resolveBeanClass(mbd, beanName); // Prepare method overrides. try { mbd.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. Object bean = resolveBeforeInstantiation(beanName, mbd); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } Object beanInstance = doCreateBean(beanName, mbd, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } }, acc); }
createBean里最核心的操作是doCreateBean,我们跟进doCreateBean里来看看其中的操作:
/** * Actually create the specified bean. Pre-creation processing has already happened * at this point, e.g. checking <code>postProcessBeforeInstantiation</code> callbacks. * <p>Differentiates between default bean instantiation, use of a * factory method, and autowiring a constructor. * @param beanName the name of the bean * @param mbd the merged bean definition for the bean * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. This parameter must be <code>null</code> except in this case. * @return a new instance of the bean * @throws BeanCreationException if the bean could not be created * @see #instantiateBean * @see #instantiateUsingFactoryMethod * @see #autowireConstructor */ protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set actualDependentBeans = new LinkedHashSet(dependentBeans.length); for (int i = 0; i < dependentBeans.length; i++) { String dependentBean = dependentBeans[i]; if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. registerDisposableBeanIfNecessary(beanName, bean, mbd); return exposedObject; }
在这里最核心的操作有两个,一个是createBeanInstance,这个方法主要是用于完成Bean的实例化,可能采用工厂方法,也可能采用构造方法new等,具体的操作根据BeanDefinition中的配置信息。另一个是populateBean方法,这个方法主要完成了依赖注入的功能。
createBean方法源码解析:
/** * Create a new instance for the specified bean, using an appropriate instantiation strategy: * factory method, constructor autowiring, or simple instantiation. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param args arguments to use if creating a prototype using explicit arguments to a * static factory method. It is invalid to use a non-null args value in any other case. * @return BeanWrapper for the new instance * @see #instantiateUsingFactoryMethod * @see #autowireConstructor * @see #instantiateBean */ protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // Make sure bean class is actually resolved at this point. Class beanClass = resolveBeanClass(mbd, beanName); if (mbd.getFactoryMethodName() != null) { return instantiateUsingFactoryMethod(beanName, mbd, args); } // Shortcut when re-creating the same bean... if (mbd.resolvedConstructorOrFactoryMethod != null) { if (mbd.constructorArgumentsResolved) { return autowireConstructor(beanName, mbd, null, args); } else { return instantiateBean(beanName, mbd); } } // Need to determine the constructor... Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) { return autowireConstructor(beanName, mbd, ctors, args); } // No special handling: simply use no-arg constructor. return instantiateBean(beanName, mbd); }
在这里我们可以看到,根据BeanDefinition中的配置信息,生成Bean的实例的方式不同,有的采用工厂方法的方式,有的采用带参的构造方法的模式,有的采用无参的构造方法的模式。我们进入instantiateBean中来看看具体的代码。
/** * Instantiate the given bean using its default constructor. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @return BeanWrapper for the new instance */ protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) { try { Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this); BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw; } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex); } }
这里使用配置的实例化策略来完成实例化工作,根据源码我们可以知道使用的CglibSubclassingInstantiationStrategy()来生成bean的代理。
下面,我们继续来看populateBean是如何完成Bean的依赖注入的
/** * Populate the bean instance in the given BeanWrapper with the property values * from the bean definition. * @param beanName the name of the bean * @param mbd the bean definition for the bean * @param bw BeanWrapper with bean instance */ protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) { PropertyValues pvs = mbd.getPropertyValues(); if (bw == null) { if (!pvs.isEmpty()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) { BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next(); if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } if (!continueWithPropertyPopulation) { return; } if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw); if (hasInstAwareBpps) { for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext(); ) { BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next(); if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor; pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } applyPropertyValues(beanName, mbd, bw, pvs); }
我们进入applyPropertyValues来看看Spring是如何真正实现依赖注入的
/** * Apply the given property values, resolving any runtime references * to other beans in this bean factory. Must use deep copy, so we * don't permanently modify this property. * @param beanName the bean name passed for better exception information * @param mbd the merged bean definition * @param bw the BeanWrapper wrapping the target object * @param pvs the new property values */ protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) { if (pvs == null || pvs.isEmpty()) { return; } MutablePropertyValues mpvs = null; List original = null; if (pvs instanceof MutablePropertyValues) { mpvs = (MutablePropertyValues) pvs; if (mpvs.isConverted()) { // Shortcut: use the pre-converted values as-is. try { bw.setPropertyValues(mpvs); return; } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } } original = mpvs.getPropertyValueList(); } else { original = Arrays.asList(pvs.getPropertyValues()); } TypeConverter converter = getCustomTypeConverter(); if (converter == null) { converter = bw; } BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter); // Create a deep copy, resolving any references for values. List deepCopy = new ArrayList(original.size()); boolean resolveNecessary = false; for (Iterator it = original.iterator(); it.hasNext();) { PropertyValue pv = (PropertyValue) it.next(); if (pv.isConverted()) { deepCopy.add(pv); } else { String propertyName = pv.getName(); Object originalValue = pv.getValue(); Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue); Object convertedValue = resolvedValue; boolean convertible = bw.isWritableProperty(propertyName) && !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); if (convertible) { convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter); } // Possibly store converted value in merged bean definition, // in order to avoid re-conversion for every created bean instance. if (resolvedValue == originalValue) { if (convertible) { pv.setConvertedValue(convertedValue); } deepCopy.add(pv); } else if (originalValue instanceof TypedStringValue && convertible) { pv.setConvertedValue(convertedValue); deepCopy.add(pv); } else { resolveNecessary = true; deepCopy.add(new PropertyValue(pv, convertedValue)); } } } if (mpvs != null && !resolveNecessary) { mpvs.setConverted(); } // Set our (possibly massaged) deep copy. try { bw.setPropertyValues(new MutablePropertyValues(deepCopy)); } catch (BeansException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Error setting property values", ex); } }
从这里,我们可以看出真正对属性值进行解析处理注入的实际BeanDefinitionValueResolver的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</code>, 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) { // We must check each value to see whether it requires a runtime reference // to another bean to be resolved. if (value instanceof RuntimeBeanReference) { RuntimeBeanReference ref = (RuntimeBeanReference) value; return resolveReference(argName, ref); } else if (value instanceof RuntimeBeanNameReference) { String ref = ((RuntimeBeanNameReference) value).getBeanName(); if (!this.beanFactory.containsBean(ref)) { throw new BeanDefinitionStoreException( "Invalid bean name '" + ref + "' in bean reference for " + argName); } return ref; } 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; return resolveInnerBean(argName, "(inner bean)", bd); } 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 (Iterator it = original.entrySet().iterator(); it.hasNext();) { Map.Entry propEntry = (Map.Entry) it.next(); Object propKey = propEntry.getKey(); Object propValue = propEntry.getValue(); if (propKey instanceof TypedStringValue) { propKey = ((TypedStringValue) propKey).getValue(); } if (propValue instanceof TypedStringValue) { propValue = ((TypedStringValue) propValue).getValue(); } copy.put(propKey, propValue); } return copy; } else if (value instanceof TypedStringValue) { // Convert value to target type here. TypedStringValue typedStringValue = (TypedStringValue) value; try { Class resolvedTargetType = resolveTargetType(typedStringValue); if (resolvedTargetType != null) { return this.typeConverter.convertIfNecessary(typedStringValue.getValue(), resolvedTargetType); } else { // No target type specified - no conversion necessary... return typedStringValue.getValue(); } } catch (Throwable ex) { // Improve the message by showing the context. throw new BeanCreationException( this.beanDefinition.getResourceDescription(), this.beanName, "Error converting typed String value for " + argName, ex); } } else { // No need to resolve value... return value; } }
在这里我们可以看到对set,map,list,properties等的解析,具体的动作请进入相关的方法来分析查看,这里不做详述了。
相关文章推荐
- Spring源码解析-实例化bean对象
- Spring源码解读之bean注入依赖
- Spring源码解析 依赖注入
- Spring应用、原理以及粗读源码系列(一)--框架总述、以Bean为核心的机制(IoC容器初始化以及依赖注入)
- spring源码解读 Bean的依赖注入
- Spring源码解析 依赖注入
- Spring源码解析 依赖注入
- Spring源码学习--Bean注入解析结果BeanDefinition
- Spring源码解析三:IOC容器的依赖注入
- SpringMVC 源代码深度解析 IOC容器(Bean实例化和依赖注入)
- Spring IOC/BeanFactory/ApplicationContext的工作流程/实现原理/初始化/依赖注入源码详解
- SpringMVC 源代码深度解析 IOC容器(Bean实例化和依赖注入)
- Spring核心学习(5)将Bean注入Bean-解析依赖
- Spring中bean的依赖注入解析
- 使用XPath解析xml实现简单的Spring IOC完成bean的依赖注入
- Spring源码解析-基于注解依赖注入
- SSM框架搭建及源码解析--bean的初始化及依赖注入(四)
- 【Spring源码--IOC容器的实现】(六)Bean的依赖注入
- Spring学习----------Bean 的三种依赖注入方式介绍
- 俩句话说清楚spring管理bean和依赖注入的原理