Spring IOC(三):依赖注入

参考书籍:《Spring技术内幕》

系列文章

Spring IOC(一):概述

Spring IOC(二):初始化

Spring IOC(三):依赖注入

Spring IOC(四):相关特性

4 IOC容器的依赖注入

上而对IoC容器的初始化过程进行了详细的分析,这个初始化过程完成的主要工作是在IoC容器中建立BeanDefinition数据映射。在此过程中并没有看到IoC容器对Bean依赖关系进行注人,接下来分析一下IoC容器是怎样对Bean的依赖关系进行注人的。

假设当前IoC容器已经载入了用户定义的Bean信息,开始分析依赖注入的原理,首先,注意到依赖注入的过程是用户第一次向IoC容器索要Bean时触发的,当然也有例外,也就是我们可以在BeanDefinition信息中通过控制lazy-init属性来让容器完成对Bean的预实例化。这个预实例化实际上也是一个完成依赖注入的过程,但它是在初始化的过程中完成的。当用户向IoC容器索要Bean时,在基本的IoC容器接口BeanFactory中,有一个getBean()的接口定义,这个接口的实现就是触发依赖注人发生的地方。为了进一步了解这个依赖注人过程的实现,下面从DefaultListableBeanFactoiy的基类AbstractBeanFactory入手去看看getBean()的实现,代码如下:

//AbstractBeanFactory类中:
 @Override
 public Object getBean(String name) throws BeansException {
     return doGetBean(name, null, null, false);
 }
 
 @Override
 public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
     return doGetBean(name, requiredType, null, false);
 }
 
 @Override
 public Object getBean(String name, Object... args) throws BeansException {
     return doGetBean(name, null, args, false);
 }

可以看到AbstractBeanFactory中的getBean()都是调用了doGetBean()方法,下面看一下这个方法:

//AbstractBeanFactory类中:
 protected <T> T doGetBean(
     String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
     throws BeansException {
 
     String beanName = transformedBeanName(name);
     Object beanInstance;
 
     // Eagerly check singleton cache for manually registered singletons.
     //先从缓存中取得Bean,处理那些已经被创建过的单件模式的Bean,对这种Bean的请求不需要重复创建
     Object sharedInstance = getSingleton(beanName);
     if (sharedInstance != null && args == null) {
         if (logger.isTraceEnabled()) {
             if (isSingletonCurrentlyInCreation(beanName)) {
                 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                              "' that is not fully initialized yet - a consequence of a circular reference");
             }
             else {
                 logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
             }
         }
         // 这里的getObjectForBeanInstance()完成的是FactoryBean的相关处理,以取得FactoryBean的生产结果
         beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
     }
     // 容器中还没有这个Bean
     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.
         // 这里对IOC容器中的BeanDefinition是否存在进行检查,检查是或否可能在当前BeanFactory中取出需要的Bean,
         // 如果在当前的工厂中取不到,那么到双亲BeanFactory中取,如果当前的双亲工厂取不到,那么就顺着双亲BeanFactory链一直向上找
         BeanFactory parentBeanFactory = getParentBeanFactory();
         if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
             // Not found -> check parent.
             String nameToLookup = originalBeanName(name);
             if (parentBeanFactory instanceof AbstractBeanFactory) {
                 return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                     nameToLookup, requiredType, args, typeCheckOnly);
             }
             else if (args != null) {
                 // Delegation to parent with explicit args.
                 return (T) parentBeanFactory.getBean(nameToLookup, args);
             }
             else if (requiredType != null) {
                 // No args -> delegate to standard getBean method.
                 return parentBeanFactory.getBean(nameToLookup, requiredType);
             }
             else {
                 return (T) parentBeanFactory.getBean(nameToLookup);
             }
         }
 
         if (!typeCheckOnly) {
             markBeanAsCreated(beanName);
         }
 
         StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
             .tag("beanName", name);
         try {
             if (requiredType != null) {
                 beanCreation.tag("beanType", requiredType::toString);
             }
             // 这里根据Bean的名字取得BeanDefinition
             RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
             checkMergedBeanDefinition(mbd, beanName, args);
 
             // Guarantee initialization of beans that the current bean depends on.
             // 获取当前Bean的所有依赖Bean,这样会触发getBean的递归调用,直到去到一个没有任何依赖的Bean为止
             String[] dependsOn = mbd.getDependsOn();
             if (dependsOn != null) {
                 for (String dep : dependsOn) {
                     if (isDependent(beanName, dep)) {
                         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                         "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                     }
                     registerDependentBean(dep, beanName);
                     try {
                         getBean(dep);
                     }
                     catch (NoSuchBeanDefinitionException ex) {
                         throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                         "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                     }
                 }
             }
 
             // Create bean instance. 要创建的Bean是单例的
             // 这里通过调用createBean方法创建singleton bean的实例,这里有一个回调函数getObject,
             // 会在getSingleto中调用ObjectFactory的createBean
             if (mbd.isSingleton()) {
                 sharedInstance = getSingleton(beanName, () -> {
                     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;
                     }
                 });
                 beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
             }
             // 创建的Bean是一个多例的
             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);
                 }
                 beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
             }
             // 其它作用域的,如:Request,Session,application,websocket
             else {
                 String scopeName = mbd.getScope();
                 if (!StringUtils.hasLength(scopeName)) {
                     throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
                 }
                 Scope scope = this.scopes.get(scopeName);
                 if (scope == null) {
                     throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                 }
                 try {
                     Object scopedInstance = scope.get(beanName, () -> {
                         beforePrototypeCreation(beanName);
                         try {
                             return createBean(beanName, mbd, args);
                         }
                         finally {
                             afterPrototypeCreation(beanName);
                         }
                     });
                     beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                 }
                 catch (IllegalStateException ex) {
                     throw new ScopeNotActiveException(beanName, scopeName, ex);
                 }
             }
         }
         catch (BeansException ex) {
             beanCreation.tag("exception", ex.getClass().toString());
             beanCreation.tag("message", String.valueOf(ex.getMessage()));
             cleanupAfterBeanCreationFailure(beanName);
             throw ex;
         }
         finally {
             beanCreation.end();
         }
     }
     // 对创建的Bean进行类型检查,requiredType参数中指定的getBean的类型
     return adaptBeanInstance(name, beanInstance, requiredType);
 }
 
 @SuppressWarnings("unchecked")
 // 对创建的Bean进行类型检查,如果没有问题就返回这个新创建的Bean,这个Bean已经是包含了依赖关系的Bean
 <T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {
     // Check if required type matches the type of the actual bean instance.
     if (requiredType != null && !requiredType.isInstance(bean)) {
         try {
             Object convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
             if (convertedBean == null) {
                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
             }
             return (T) convertedBean;
         }
         catch (TypeMismatchException ex) {
             if (logger.isTraceEnabled()) {
                 logger.trace("Failed to convert bean '" + name + "' to required type '" +
                              ClassUtils.getQualifiedName(requiredType) + "'", ex);
             }
             throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
         }
     }
     return (T) bean;
 }

这个就是依赖注入的入口,在这里触发了依赖注入,而依赖注入的发生是在容器中的BeanDefinition数据已经建立好的前提下进行的。程序=数据+算法。前面的BeanDefinition就是数据,下面看看这些数据是怎样为依赖注入服务的。虽然依赖注人的过程不涉及复杂的算法问题,但这个过程也不简单,因为我们都知道,对于loC容器的使用,Spring提供了许多的参数配置,毎一个参数配置实际上代表了一个IOC容器的实现特性,这些特性的实现很多都需要在依赖注入的过程中或者对Bean进行生命周期管理的过程中完成。

关于这个依赖注入的详细过程会在下面进行分析,在下图中可以看到依赖注入的一个大致过程:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MIubl8v0-1640347862850)(https://b3logfile.com/file/2021/12/image-acbb8f58.png)]

重点来说,getBean()是依赖注入的起点之后会调用createBean(),下面通过createBean()代码来了解这个实现过程。在这个过程中,Bean对象会依据BeanDefinition定义的要求生成。

AbstractAutowireCapableBeanFactory中实现了这个createBean()createBean()不但生成了需要
的Bean,还对Bean初始化进行了处理。如下面代码:

//AbstractAutowireCapableBeanFactory类中:
 @Override
 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
     throws BeanCreationException {
 
     if (logger.isTraceEnabled()) {
         logger.trace("Creating instance of bean '" + beanName + "'");
     }
     RootBeanDefinition mbdToUse = mbd;
 
     // Make sure bean class is actually resolved at this point, and
     // clone the bean definition in case of a dynamically resolved Class
     // which cannot be stored in the shared merged bean definition.
     // 这里判断需要创建的bean是否可以实例化,这个类是否可以通过类装载器来载入
     Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
     if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
         mbdToUse = new RootBeanDefinition(mbd);
         mbdToUse.setBeanClass(resolvedClass);
     }
 
     // Prepare method overrides.
     try {
         mbdToUse.prepareMethodOverrides();
     }
     catch (BeanDefinitionValidationException ex) {
         throw new BeanDefinitionStoreException(mbdToUse.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, mbdToUse);
         if (bean != null) {
             return bean;
         }
     }
     catch (Throwable ex) {
         throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                                         "BeanPostProcessor before instantiation of bean failed", ex);
     }
     // 创建Bean的调用,去创建Bean
     try {
         Object beanInstance = doCreateBean(beanName, mbdToUse, args);
         if (logger.isTraceEnabled()) {
             logger.trace("Finished creating instance of bean '" + beanName + "'");
         }
         return beanInstance;
     }
     catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
         // A previously detected exception with proper bean creation context already,
         // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
         throw ex;
     }
     catch (Throwable ex) {
         throw new BeanCreationException(
             mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
     }
 }
 
 // Bean的生成
 protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
     throws BeanCreationException {
 
     // Instantiate the bean.
     BeanWrapper instanceWrapper = null;
     // 如果是一个单例的,先将缓存中的移除
     if (mbd.isSingleton()) {
         instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
     }
     // 这里是创建Bean的地方,由createBeanInstance完成
     if (instanceWrapper == null) {
         instanceWrapper = createBeanInstance(beanName, mbd, args);
     }
     Object bean = instanceWrapper.getWrappedInstance();
     Class<?> beanType = instanceWrapper.getWrappedClass();
     if (beanType != NullBean.class) {
         mbd.resolvedTargetType = beanType;
     }
 
     // Allow post-processors to modify the merged bean definition.
     synchronized (mbd.postProcessingLock) {
         if (!mbd.postProcessed) {
             try {
                 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
             }
             catch (Throwable ex) {
                 throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                 "Post-processing of merged bean definition failed", ex);
             }
             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.isTraceEnabled()) {
             logger.trace("Eagerly caching bean '" + beanName +
                          "' to allow for resolving potential circular references");
         }
         addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
     }
 
     // Initialize the bean instance.
     // 这里是对Bean的初始化,依赖注入往往在这里发生,exposedObject在初始化处理完成之后会
     // 返回作为依赖注入完成后的Bean
     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<String> actualDependentBeans = new LinkedHashSet<>(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 " +
                                                                "'getBeanNamesForType' 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;
 }

在这里我们看到,与依赖注人关系特别密切的方法有createBeanlnstance()populateBean(),下面分别介绍这两个方法。在createBeanlnstance()中生成了Bean所包含的Java对象,这个对象的生成有很多种不同的方式,可以通过工厂方法生成,也可以通过容器的autowire特性生成,这些生成方式都是由相关的BeanDefinition来指定的。如下代码所示,可以看到不同生成方式对应的实现。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
     // Make sure bean class is actually resolved at this point.
     //确定创建Bean实例的类是可以实例化的
     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());
     }
 
     Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
     if (instanceSupplier != null) {
         return obtainFromSupplier(instanceSupplier, beanName);
     }
     // 这里使用工厂的方式实例化
     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);
         }
     }
 
     // Candidate constructors for autowiring?
     // 使用构造函数的方法实例化
     Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
     if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
         mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
         return autowireConstructor(beanName, mbd, ctors, args);
     }
 
     // Preferred constructors for default construction?
     ctors = mbd.getPreferredConstructors();
     if (ctors != null) {
         return autowireConstructor(beanName, mbd, ctors, null);
     }
 
     // No special handling: simply use no-arg constructor.
     // 使用默认的构造函数对Bean实例化
     return instantiateBean(beanName, mbd);
 }
 
 // 最常见的实例化过程instantiateBean
 protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
     try {
         Object beanInstance;
         if (System.getSecurityManager() != null) {
             beanInstance = AccessController.doPrivileged(
                 (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
                 getAccessControlContext());
         }
         else {
             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);
     }
 }

这里用CGLIB对Bean进行实例化,CGLIB是一个常用的字节码生成器的类库,它提供了一系列的API来提供生成和转换Java的字节码的功能。在Spring AOP中也使用CGLIB对Java的字节码进行增强。在loC容器中,要了解怎样使用CGLIB来生成Bean对象,需要看一下SimplelnstantiationStrategy类。这个类是Spring用来生成Bean对象的默认类,它提供了两种实例化Java对象的方法,一种是通过BeanUtils,它使用了JVM的反射功能,一种是通过前面提到的CGUB来生成。如下代码:

 public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
final Constructor<?> ctor, Object... args) {

if (!bd.hasMethodOverrides()) {
if (System.getSecurityManager() != null) {
// use own privileged to change accessibility (when security is on)
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(ctor);
return null;
});
}
//使用BeanUtils实例化Bean,这个BeanUtils的实例化通过 Constructor 来实例化Bean,利用JVM反射的功能
return BeanUtils.instantiateClass(ctor, args);
}
else {
//使用CGLIB来实例化对象
return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
}
}

到这里已经分析了实例化Bean对象的整个过程,在实例化Bean对象生成的基础上,再介绍一下Spring是怎样对这些对象进行处理的,也就是Bean对象生成以后,怎样把这些Bean对象的依赖关系设置好,完成整个依赖注入过程。这个过程涉及对各种Bean对象的属性的处理过程(即依赖关系处理的过程 ) ,这些依赖关系处理的依据就是已经解析得到的BeanDefinitione要详细了解这个过程,需要回到前面的populateBean方法,这个方法在AbstractAutowireCapableBeanFactory中的实现如下代码所示:

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
                           final Constructor<?> ctor, Object... args) {
 
     if (!bd.hasMethodOverrides()) {
         if (System.getSecurityManager() != null) {
             // use own privileged to change accessibility (when security is on)
             AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                 ReflectionUtils.makeAccessible(ctor);
                 return null;
             });
         }
         //使用BeanUtils实例化Bean,这个BeanUtils的实例化通过 Constructor 来实例化Bean,利用JVM反射的功能
         return BeanUtils.instantiateClass(ctor, args);
     }
     else {
         //使用CGLIB来实例化对象
         return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
     }
 }

这里通过使用BeanDefinitionValueResolver来对BeanDefinition进行解析,然后注入到property中。下面到BeanDefinitionValueResolver中去看一下解析过程的实现,以对Bean reference进
行解析为例,具体的对Bean reference进行解析的过程如下:

//BeanDefinitionValueResolver类中:
 // 解析一个引用依赖,然后注入到property中
 private Object resolveReference(Object argName, RuntimeBeanReference ref) {
     try {
         Object bean;
         //RuntimeBeanReference取得reference的类型,这个RuntimeBeanReference是在载入BeanDefinition时配置的
         Class<?> beanType = ref.getBeanType();
         //如果ref是在双亲IOC容器中,那么就到双亲IOC容器中获取
         if (ref.isToParent()) {
             BeanFactory parent = this.beanFactory.getParentBeanFactory();
             if (parent == null) {
                 throw new BeanCreationException(
                     this.beanDefinition.getResourceDescription(), this.beanName,
                     "Cannot resolve reference to bean " + ref +
                     " in parent factory: no parent factory available");
             }
             if (beanType != null) {
                 bean = parent.getBean(beanType);
             }
             else {
                 bean = parent.getBean(String.valueOf(doEvaluate(ref.getBeanName())));
             }
         }
         // 在当前IOC容器中去获取Bean,这里会触发一个getBean,如果依赖注入没有发生,这里会触发相应的依赖注入的发生
         else {
             String resolvedName;
             if (beanType != null) {
                 NamedBeanHolder<?> namedBean = this.beanFactory.resolveNamedBean(beanType);
                 bean = namedBean.getBeanInstance();
                 resolvedName = namedBean.getBeanName();
             }
             else {
                 resolvedName = String.valueOf(doEvaluate(ref.getBeanName()));
                 bean = this.beanFactory.getBean(resolvedName);
             }
             this.beanFactory.registerDependentBean(resolvedName, this.beanName);
         }
         if (bean instanceof NullBean) {
             bean = null;
         }
         return bean;
     }
     catch (BeansException ex) {
         throw new BeanCreationException(
             this.beanDefinition.getResourceDescription(), this.beanName,
             "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);
     }
 }
 
 //对以集合为属性的引用的依赖项,对每一个依赖项进行解析
 /**
 

 * 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<>(ml.size());
     for (int i = 0; i < ml.size(); i++) {
         resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));
     }
     return resolved;
 }

这两种属性的注人都调用了resolveValuelfNecessary(),这个方法包含了所有对注入类型的处理。下面看一下resolveValuelfNecessary()的实现:

// 这里对各种属性进行解析
 @Nullable
 public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {
     // We must check each value to see whether it requires a runtime reference
     // to another bean to be resolved.
     //这里对RuntimeBeanReference进行解析,RuntimeBeanReference是在对BeanDefinition进行解析时生成的数据对象
     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(doEvaluate(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 DependencyDescriptor) {
         Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
         Object result = this.beanFactory.resolveDependency(
             (DependencyDescriptor) value, this.beanName, autowiredBeanNames, this.typeConverter);
         for (String autowiredBeanName : autowiredBeanNames) {
             if (this.beanFactory.containsBean(autowiredBeanName)) {
                 this.beanFactory.registerDependentBean(autowiredBeanName, this.beanName);
             }
         }
         return result;
     }
     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();
         original.forEach((propKey, propValue) -> {
             if (propKey instanceof TypedStringValue) {
                 propKey = evaluate((TypedStringValue) propKey);
             }
             if (propValue instanceof TypedStringValue) {
                 propValue = evaluate((TypedStringValue) propValue);
             }
             if (propKey == null || propValue == null) {
                 throw new BeanCreationException(
                     this.beanDefinition.getResourceDescription(), this.beanName,
                     "Error converting Properties key/value pair for " + argName + ": resolved to null");
             }
             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 if (value instanceof NullBean) {
         return null;
     }
     else {
         return evaluate(value);
     }
 }

在完成这个解析过程后,已经为依赖注人准备好了条件,依赖已经准备好,其中处理属性的方式是各种各样的。然后需要真正把Bean对象设置到它所依赖的另一个Bean的属性中去的地方,依赖注人的发生是在BeanWrappersetPropertyValues()中调用的,具体的完成却是在AbstractNestablePropertyAccessor类的processKeyedProperty中实现的,如下代码:

private void processKeyedProperty(PropertyTokenHolder tokens, PropertyValue pv) {
    Object propValue = getPropertyHoldingValue(tokens);
    PropertyHandler ph = getLocalPropertyHandler(tokens.actualName);
    if (ph == null) {
        throw new InvalidPropertyException(
            getRootClass(), this.nestedPath + tokens.actualName, "No property handler found");
    }
    Assert.state(tokens.keys != null, "No token keys");
    String lastKey = tokens.keys[tokens.keys.length - 1];
    //对Array类型的属性注入
    if (propValue.getClass().isArray()) {
        Class<?> requiredType = propValue.getClass().getComponentType();
        int arrayIndex = Integer.parseInt(lastKey);
        Object oldValue = null;
        try {
            if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
                oldValue = Array.get(propValue, arrayIndex);
            }
            Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
                                                       requiredType, ph.nested(tokens.keys.length));
            int length = Array.getLength(propValue);
            if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
                Class<?> componentType = propValue.getClass().getComponentType();
                Object newArray = Array.newInstance(componentType, arrayIndex + 1);
                System.arraycopy(propValue, 0, newArray, 0, length);
                int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
                String propName = tokens.canonicalName.substring(0, lastKeyIndex);
                setPropertyValue(propName, newArray);
                propValue = getPropertyValue(propName);
            }
            Array.set(propValue, arrayIndex, convertedValue);
        }
        catch (IndexOutOfBoundsException ex) {
            throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
                                               "Invalid array index in property path '" + tokens.canonicalName + "'", ex);
        }
    }
    // 对List类型属性注入
    else if (propValue instanceof List) {
        Class<?> requiredType = ph.getCollectionType(tokens.keys.length);
        List<Object> list = (List<Object>) propValue;
        int index = Integer.parseInt(lastKey);
        Object oldValue = null;
        if (isExtractOldValueForEditor() && index < list.size()) {
            oldValue = list.get(index);
        }
        Object convertedValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
                                                   requiredType, ph.nested(tokens.keys.length));
        int size = list.size();
        if (index >= size && index < this.autoGrowCollectionLimit) {
            for (int i = size; i < index; i++) {
                try {
                    list.add(null);
                }
                catch (NullPointerException ex) {
                    throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
                                                       "Cannot set element with index " + index + " in List of size " +
                                                       size + ", accessed using property path '" + tokens.canonicalName +
                                                       "': List does not support filling up gaps with null elements");
                }
            }
            list.add(convertedValue);
        }
        else {
            try {
                list.set(index, convertedValue);
            }
            catch (IndexOutOfBoundsException ex) {
                throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
                                                   "Invalid list index in property path '" + tokens.canonicalName + "'", ex);
            }
        }
    }
    // 对Map类型属性注入
    else if (propValue instanceof Map) {
        Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);
        Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);
        Map<Object, Object> map = (Map<Object, Object>) propValue;
        // IMPORTANT: Do not pass full property name in here - property editors
        // must not kick in for map keys but rather only for map values.
        TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
        Object convertedMapKey = convertIfNecessary(null, null, lastKey, mapKeyType, typeDescriptor);
        Object oldValue = null;
        if (isExtractOldValueForEditor()) {
            oldValue = map.get(convertedMapKey);
        }
        // Pass full property name and old value in here, since we want full
        // conversion ability for map values.
        Object convertedMapValue = convertIfNecessary(tokens.canonicalName, oldValue, pv.getValue(),
                                                      mapValueType, ph.nested(tokens.keys.length));
        map.put(convertedMapKey, convertedMapValue);
    }
    // 其它类型属性注入
    else {
        throw new InvalidPropertyException(getRootClass(), this.nestedPath + tokens.canonicalName,
                                           "Property referenced in indexed property path '" + tokens.canonicalName +
                                           "' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
    }
}

在Bean的创建和对象依赖注人的过程中,需要依据BeanDefinition中的信息来递归地完成依赖注入。从上面的几个递归过程中可以看到,这些递归都是以getBean()为入口的。一个递归是在上下文体系中查找需要的Bean和创建Bean的递归调用,另一个递归是在依赖注入时,通过递归调用容器的getBean()方法,得到当前Bean的依赖Bean,同时也触发对依赖Bean的创建和注入。在对Bean的属性进行依赖注入时,解析的过程也是一个递归的过程。这样,根据依赖关系,一层一层地完成Bean的创建和注入,直到最后完成当前Bean的创建。有了这个顶层Bean的创建和对它的属性依赖注入的完成,意味着和当前Bean相关的整个依赖链的注入也完成了。

在Bean创建和依赖注入完成以后,在loC容器中建立起一系列依靠依赖关系联系起来的Bean,这个Bean已经不是简单的java对象了。该Bean系列以及Bean之间的依赖关系建立完成以后,通过loC容器的相关接口方法,就可以非常方便地供上层应用使用了。继续以水桶为例,到这里,我们不但找到了水源,而且成功地把水装到了水桶中,同时对水桶里的水完成了一系列的处理,比如消毒、煮沸,尽管还是水,但经过一系列的处理以后,这些水已经是开水了,可以直接饮用了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值