为了账号安全,请及时绑定邮箱和手机立即绑定

死磕Spring源码-依赖注入

标签:
Java

我们分析了IOC容器的初始化,可以看出初始化其实就是在IoC容器中建立BeanDefinition数据映射,但并没有对Bean的依赖关系进行注入,依赖注入是用户第一次向IoC容器索要Bean的时候触发的,调用BeanFactory的getBean方法将触发依赖注入,这个时候才会创建对象实例,也可以通过设置bean的lazy-init属性来让bean的实例化过程在容器初始化的过程就完成,如果通过设置Bean的lazy-init属性,那么在容器初始化这个bean的时候就会调用getBean去触发依赖注入。

如果doGetBean方法在当前的IoC容器中找不到Bean,会到双亲BeanFactory中去取,如果当前的双亲容器找不到那就再顺着双亲BeanFactory链一直向上寻找。

get某一个Bean的时候会依赖注入其所依赖的所有的Bean,触发getBean的递归调用,直到取到一个没有任何依赖的bean为止。

依赖注入实现过程图:

图片描述

依赖注入比较重要的两个方法:createBeanInstance和populateBean

createBeanInstance实例化Bean对象

图片描述

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
     // Instantiate the bean.
     BeanWrapper instanceWrapper = null;
     if (mbd.isSingleton()) {
          instanceWrapper = 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<Object>() {
               @Override
               public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
               }
          });
     }

     // Initialize the bean instance.
     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;
}

createBeanInstance中生成了Bean所包含的Java对象,Spring中用SimpleInstantiationStrategy类来生成Bean对象的实例,实例化Java对象的方法有两种:

1、通过BeanUtils,它使用了JVM的反射功能来生成Java对象实例

2、用CGLIB来生成,CGLIB是一种常用的字节码生成器的类库

@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
     // Don't override the class with CGLIB if no overrides.
     if (bd.getMethodOverrides().isEmpty()) {
          Constructor<?> constructorToUse;
          synchronized (bd.constructorArgumentLock) {
               constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
               if (constructorToUse == null) {
                    final Class<?> clazz = bd.getBeanClass();
                    if (clazz.isInterface()) {
                         throw new BeanInstantiationException(clazz, "Specified class is an interface");
                    }
                    try {
                         if (System.getSecurityManager() != null) {
                              constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
                                   @Override
                                   public Constructor<?> run() throws Exception {
                                        return clazz.getDeclaredConstructor((Class[]) null);
                                   }
                              });
                         }
                         else {
                              constructorToUse =     clazz.getDeclaredConstructor((Class[]) null);
                         }
                         bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                    }
                    catch (Throwable ex) {
                         throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                    }
               }
          }
//通过BeanUtils进行实例化,从这个方法中可以看到具体调用了ctor.newInstance()方法
          return BeanUtils.instantiateClass(constructorToUse);
     }
     else {
          // 使用CGLIB来实例化对象
          return instantiateWithMethodInjection(bd, beanName, owner);
     }
}

Bean对象生成好了之后,Spring用BeanWrapper来持有创建出来的Bean对象,接下来Spring通过populateBean方法来把这些Bean对象的依赖关系设置好,以完成整个依赖注入的过程。

依赖注入的发生是在BeanWrapper的setPropertyValues中,具体的实现过程在其子类BeanWrapperImpl;createBeanInstance方法返回值就是一个BeanWrapper对象。再把BeanWrapper对象作为一个形参传入populateBean中。populateBean是对Bean的初始化,依赖注入就发生在这里。

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
     //这里通过解析BeanDefinition来获取property值
     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的注入,可以根据Bean的名字或类型来完成Bean的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, mbd.allowCaching);
          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);
}

populateBean解析BeanDefinition中设置的property值,获取到Bean的依赖信息并设置Bean的依赖关系。通过使用BeanDefinitionResolver对BeanDefinition进行解析,然后注入到property中。
resolveValueIfNecessary方法包含了对所有的注入类型的处理,里面包含各种instanceof的判断,比如RuntimeBeanReference,Array,List,Map等数据类型,RuntimeBeanReference是在对BeanDefinition进行解析时生成的数据对象,是在载入BeanDefinition时根据配置生成的,如果RuntimeBeanReference是在双亲容器中则从双亲容器中去获取Bean(通过getBean方法)。

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();
               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();
     }

     // 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);
     }
}

完成解析过程后就已经是为依赖注入做好了准备条件,依赖注入的发生是在BeanWrapper的setPropertyValues中,具体的实现过程在其子类BeanWrapperImpl。

setPropertyValue的方法调用栈:

图片描述

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消