Spring源码解析三:IOC容器的依赖注入
一、Bean对象创建的时机
依赖注入是在Bean对象创建的时候完成的,那么第一个问题来了,Bean对象什么时候创建?
Bean对象的创建是在getBean方法被调用的时候发生的,而在Spring中有两个场景会触发getBean方法被调用。
1、单例模式并且是非延迟加载的对象,会在IOC容器初始化的时候被创建且初始化。
2、非单例模式或者是延迟加载的对象,是应用第一次向容器索要该Bean对象的时候被创建且初始化。
虽然入口场景不同,但是Bean对象创建的过程是一样的,都是调用AbstractBeanFactory中getBean方法。
我们来重点看下DefaultListableBeanFactory的preInstantiateSingletons 的源码,就能对前面提到的规则有一个很好的理解。
- public void preInstantiateSingletons() throws BeansException {
- if (this.logger.isInfoEnabled()) {
- this.logger.info("Pre-instantiating singletons in " + this);
- }
- synchronized (this.beanDefinitionMap) {
- for (String beanName : this.beanDefinitionNames) {
- RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
- if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
- if (isFactoryBean(beanName)) {
- final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
- boolean isEagerInit;
- if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
- isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
- public Boolean run() {
- return ((SmartFactoryBean) factory).isEagerInit();
- }
- }, getAccessControlContext());
- }
- else {
- isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();
- }
- if (isEagerInit) {
- getBean(beanName);
- }
- }
- else {
- getBean(beanName);
- }
- }
- }
- }
- }
这里验证了第一个规则,容器初始化时,会对单例并且是非延迟加载的对象进行实例化。
二、依赖注入的源码分析
这里以DefaultListableBeanFactory的基类AbstractBeanFactory中的getBean()方法来进行介绍。
- public Object getBean(String name) throws BeansException {
- return doGetBean(name, null, null, false);
- }
- protected <T> T doGetBean(
- final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
- throws BeansException {
- final String beanName = transformedBeanName(name);
- Object bean;
- // 先尝试从缓存中获取bean,对于那些单例模式的Bean,不需要重复创建。
- 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 + "'");
- }
- }
//这里处理的是FactoryBean相关的处理,以取得FactoryBean的生产结果- 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);
- }
- //对IOC容器中BeanDefinition是否存在进行检查,如果在当前Bean工厂中找不到需要的Bean,则到双亲BeanFactory中去查找,依次类推
- 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 (T) parentBeanFactory.getBean(nameToLookup, args);
- }
- else {
- // No args -> delegate to standard getBean method.
- return parentBeanFactory.getBean(nameToLookup, requiredType);
- }
- }
- if (!typeCheckOnly) {
- markBeanAsCreated(beanName);
- }
- //根据BeanName取得BeanDefinition
- final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
- checkMergedBeanDefinition(mbd, beanName, args);
- // 获取当前Bean依赖的Bean,这里可能会触发getBean方法的递归调用,直到没有任何以来的Bean为止。
- String[] dependsOn = mbd.getDependsOn();
- if (dependsOn != null) {
- for (String dependsOnBean : dependsOn) {
- 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 = 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);
- }
- }
- }
- // 对新创建的Bean进行类型检查,如果没有问题就返回这个Bean,这个Bean此时已经包含了依赖关系的Bean
- if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
- throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
- }
- return (T) bean;
- }
接下来看看Bean对象通过createBean方法是如何被创建的,在类AbstractAutowireCapableBeanFactory中createBean()调用doCreateBean()
- protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
- // Instantiate the bean.
- BeanWrapper instanceWrapper = null;
//如果是单例模式,现将缓存中的同名Bean删除- if (mbd.isSingleton()) {
- instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
- }
- if (instanceWrapper == null) {
//这里是创建Bean的地方- 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);
- }
- });
- }
- // 这里是对Bean初始化,依赖注入就是在这里完成的,exposedObject会作为Bean依赖注入完成后的对象返回
- Object exposedObject = bean;
- try {
- populateBean(beanName, mbd, instanceWrapper);
- if (exposedObject != null) {
- 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<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
- for (String dependentBean : dependentBeans) {
- 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.
- try {
- registerDisposableBeanIfNecessary(beanName, bean, mbd);
- }
- catch (BeanDefinitionValidationException ex) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
- }
- return exposedObject;
- }
代码片段中标记的两处,一个是Bean对象的生成;另一个Bean的初始化,即依赖注入。下面分别来这两个方法的实现:
1、createBeanInstance
- 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 (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName,
- "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
- }
- if (mbd.getFactoryMethodName() != null) {
- return instantiateUsingFactoryMethod(beanName, mbd, args);
- }
- // Shortcut when re-creating the same bean...
- boolean resolved = false;
- boolean autowireNecessary = false;
- if (args == null) {
- synchronized (mbd.constructorArgumentLock) {
- if (mbd.resolvedConstructorOrFactoryMethod != null) {
- resolved = true;
- autowireNecessary = mbd.constructorArgumentsResolved;
- }
- }
- }
- if (resolved) {
- if (autowireNecessary) {
- return autowireConstructor(beanName, mbd, null, null);
- }
- 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);
- }
这里实例化Bean有三种方式:工厂方法、构造函数以及默认的实例化策略CGLB。前两种方式我们都很熟悉,这个CGLB是一个常用的字节码生成器的类库,它提供了一系列的API来提供生成和转换JAVA的字节码的功能,在AOP中也是用CGLB对JAVA的字节码进行增强。
CGLB创建对象的过程在CglibSubclassingInstantiationStrategy中:
- public Object instantiate(Constructor ctor, Object[] args) {
- Enhancer enhancer = new Enhancer();
- enhancer.setSuperclass(this.beanDefinition.getBeanClass());
- enhancer.setCallbackFilter(new CallbackFilterImpl());
- enhancer.setCallbacks(new Callback[] {
- NoOp.INSTANCE,
- new LookupOverrideMethodInterceptor(),
- new ReplaceOverrideMethodInterceptor()
- });
- return (ctor == null) ?
- enhancer.create() :
- enhancer.create(ctor.getParameterTypes(), args);
- }
2、populateBean
- 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 (BeanPostProcessor bp : getBeanPostProcessors()) {
- if (bp instanceof InstantiationAwareBeanPostProcessor) {
- InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
- if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
- continueWithPropertyPopulation = false;
- break;
- }
- }
- }
- }
- if (!continueWithPropertyPopulation) {
- return;
- }
- //开始进行依赖注入过程,先处理autoWire的注入
- 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 (BeanPostProcessor bp : getBeanPostProcessors()) {
- if (bp instanceof InstantiationAwareBeanPostProcessor) {
- InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
- pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
- if (pvs == null) {
- return;
- }
- }
- }
- }
- if (needsDepCheck) {
- checkDependencies(beanName, mbd, filteredPds, pvs);
- }
- }
- //对属性进行注入
- applyPropertyValues(beanName, mbd, bw, pvs);
- }
对属性进行注入:
- protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
- if (pvs == null || pvs.isEmpty()) {
- return;
- }
- MutablePropertyValues mpvs = null;
- List<PropertyValue> original;
- if (System.getSecurityManager()!= null) {
- if (bw instanceof BeanWrapperImpl) {
- ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
- }
- }
- 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<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
- boolean resolveNecessary = false;
- for (PropertyValue pv : original) {
- if (pv.isConverted()) {
- deepCopy.add(pv);
- }
- else {
- String propertyName = pv.getName();
- Object originalValue = pv.getValue();
//对BeanDefinition进行解析- 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 (convertible && originalValue instanceof TypedStringValue &&
- !((TypedStringValue) originalValue).isDynamic() &&
- !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
- pv.setConvertedValue(convertedValue);
- deepCopy.add(pv);
- }
- else {
- resolveNecessary = true;
- deepCopy.add(new PropertyValue(pv, convertedValue));
- }
- }
- }
- if (mpvs != null && !resolveNecessary) {
- mpvs.setConverted();
- }
- // 真正依赖注入的地方,实现类为WrapperImpl
- try {
- bw.setPropertyValues(new MutablePropertyValues(deepCopy));
- }
- catch (BeansException ex) {
- throw new BeanCreationException(
- mbd.getResourceDescription(), beanName, "Error setting property values", ex);
- }
- }
在类BeanDefinitionValueResolver中对BeanDefinition进行解析
- 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 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;
- return resolveInnerBean(argName, "(inner bean)", 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) {
- // Improve the message by showing the context.
- throw new 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 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) {
- // Improve the message by showing the context.
- throw new BeanCreationException(
- this.beanDefinition.getResourceDescription(), this.beanName,
- "Error converting typed String value for " + argName, ex);
- }
- }
- else {
- return evaluate(value);
- }
- }
这里可以看到不同类型的属性,常见的list、map、array等,我们最关注的还是依赖的Bean是如何解析的,请看第6行:
- private Object resolveReference(Object argName, RuntimeBeanReference ref) {
- try {
- String refName = ref.getBeanName();
- refName = String.valueOf(evaluate(refName));
//如果引用的Bean在双亲容器中,就从双亲容器中查找- 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);
- }
//如果在当前容器中获取Bean,会触发一个getBean的过程,如果依赖注入没有发生,也会相应触发该过程- else {
- 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);
- }
- }
到这里已经将依赖注入所需要的数据全都准备OK,现在要做的就是将这些属性设置对应的Bean中。而属性设置发生在类BeanWrapperImpl中的setPropertyValue方法中
- public void setPropertyValue(PropertyValue pv) throws BeansException {
- PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
- if (tokens == null) {
- String propertyName = pv.getName();
- BeanWrapperImpl nestedBw;
- try {
- nestedBw = getBeanWrapperForPropertyPath(propertyName);
- }
- catch (NotReadablePropertyException ex) {
- throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
- "Nested property in path '" + propertyName + "' does not exist", ex);
- }
- tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));
- if (nestedBw == this) {
- pv.getOriginalPropertyValue().resolvedTokens = tokens;
- }
- nestedBw.setPropertyValue(tokens, pv);
- }
- else {
- setPropertyValue(tokens, pv);
- }
- }
属性设置的具体位置在第17行,有兴趣的可以进去看下。。。。。。。。
到此,我们已经完成了找到水源、将水装入木桶、对桶里的水进行处理,如消毒、煮沸。那么现在可以使用IOC容器中存在的Bean对象了。
Spring源码解析三:IOC容器的依赖注入的更多相关文章
- spring源码解析之IOC容器(一)
学习优秀框架的源码,是提升个人技术水平必不可少的一个环节.如果只是停留在知道怎么用,但是不懂其中的来龙去脉,在技术的道路上注定走不长远.最近,学习了一段时间的spring源码,现在整理出来,以便日后温 ...
- spring源码解析之IOC容器(三)——依赖注入
上一篇主要是跟踪了IOC容器对bean标签进行解析之后存入Map中的过程,这些bean只是以BeanDefinition为载体单纯的存储起来了,并没有转换成一个个的对象,今天继续进行跟踪,看一看IOC ...
- spring源码解析之IOC容器(二)------加载和注册
上一篇跟踪了IOC容器对配置文件的定位,现在我们继续跟踪代码,看看IOC容器是怎么加载和注册配置文件中的信息的.开始之前,首先我们先来了解一下IOC容器所使用的数据结构-------BeanDefin ...
- spring源码解析之IOC容器(四)——属性注入
上一篇跟踪了bean的创建过程,接下来,我们继续跟踪bean的属性填充的过程.先回到doCreateBean方法,代码如下: protected Object doCreateBean(final S ...
- 【spring源码分析】IOC容器初始化(三)
前言:在[spring源码分析]IOC容器初始化(二)中已经得到了XML配置文件的Document实例,下面分析bean的注册过程. XmlBeanDefinitionReader#registerB ...
- 【spring源码分析】IOC容器初始化(总结)
前言:在经过前面十二篇文章的分析,对bean的加载流程大致梳理清楚了.因为内容过多,因此需要进行一个小总结. 经过前面十二篇文章的漫长分析,终于将xml配置文件中的bean,转换成我们实际所需要的真正 ...
- 【spring源码分析】IOC容器初始化(四)
前言:在[spring源码分析]IOC容器初始化(三)中已经分析了BeanDefinition注册之前的一些准备工作,下面将进入BeanDefinition注册的核心流程. //DefaultBean ...
- 转 Spring源码剖析——核心IOC容器原理
Spring源码剖析——核心IOC容器原理 2016年08月05日 15:06:16 阅读数:8312 标签: spring源码ioc编程bean 更多 个人分类: Java https://blog ...
- 【spring源码分析】IOC容器初始化(二)
前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...
- 【spring源码分析】IOC容器初始化(七)
前言:在[spring源码分析]IOC容器初始化(六)中分析了从单例缓存中加载bean对象,由于篇幅原因其核心函数 FactoryBeanRegistrySupport#getObjectFromFa ...
随机推荐
- dom对象中的this和event.target区别
1.this是事件冒泡,动态变化.先触发内部事件,由内到外的执行. <script> function testdiv(val){ console.log(val.id); } funct ...
- MySQL数据库面试
1. MySql的存储引擎的不同 特点 Myisam BDB Memory InnoDB Archive 存储限制 没有 没有 有 64TB 没有 事务安全 支持 支持 锁机制 表锁 页锁 ...
- UVa 10132 - File Fragmentation
题目大意:有n个相同的文件,每个文件从中间分为两半,现在给你这2n个文件碎片,求原来完整的文件. 找出文件碎片长度的最大值和最小值,二者相加可得到原来文件的长度len.然后逐个进行拼接,将拼接后长度等 ...
- 【MongoDb基础】插入数据
以mydb为事例数据库. 切换到mydb数据库. use mydb 1. insert函数. db.users.insert({name:"Derek",age:18}) 该函数会 ...
- 建立ipython集群
启动controller ipcontroller -- ip = ipaddress 设置ssh免登陆 因为需要分发文件,采用ssh通信,所以需要配置ssh免登陆 分发配置文件 scp contro ...
- php循环生成的表单如何获得其各项值案例
思路:输入框和按钮是用for循环生成的,不但要获取输入框里的各项值,并且要获取点击按钮的值,要知道是那个按钮被点击了,这里以生成5个为例.如图: 这是提交页面,点击的是“小米”. 这是显示结果,测试显 ...
- 配置Log4J(转载)
Log4J的配置文件(Configuration File)就是用来设置记录器的级别.存放器和布局的,它可接key=value格式的设置或xml格式的设置信息.通过配置,可以创建出Log4J的运行环境 ...
- Delphi 常用API 函数
Delphi 常用API 函数 AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小 AnyPopup 判断屏幕上是否存在任何弹出式窗口 ArrangeIconic ...
- Eclipse 打开文件所在文件夹
右击文件 > Show In > System Explorer
- mfix模拟流化床燃烧帮助收敛的方法
1.在反应速率里用rate_limit函数:2.初始床料中可以添加一部分碳和灰.下面给出详细解释: 1.c3m生成的化学反应速率中有一个这样的函数: double precision function ...