zoukankan      html  css  js  c++  java
  • spring源码解析之IOC容器(四)——属性注入

      上一篇跟踪了bean的创建过程,接下来,我们继续跟踪bean的属性填充的过程。先回到doCreateBean方法,代码如下:

      1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
      2             throws BeanCreationException {
      3 
      4         // Instantiate the bean.
      5         BeanWrapper instanceWrapper = null;
      6         if (mbd.isSingleton()) {
      7             //如果是单例,先把缓存中的同名Bean清除
      8             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
      9         }
     10         //如果缓存中没有
     11         if (instanceWrapper == null) {
     12             //则创建一个实例
     13             instanceWrapper = createBeanInstance(beanName, mbd, args);
     14         }
     15         final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
     16         Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
     17         mbd.resolvedTargetType = beanType;
     18 
     19         // Allow post-processors to modify the merged bean definition.
     20         synchronized (mbd.postProcessingLock) {
     21             if (!mbd.postProcessed) {
     22                 try {
     23                     //使用后置处理器进行处理
     24                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
     25                 }
     26                 catch (Throwable ex) {
     27                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     28                             "Post-processing of merged bean definition failed", ex);
     29                 }
     30                 mbd.postProcessed = true;
     31             }
     32         }
     33 
     34         // Eagerly cache singletons to be able to resolve circular references
     35         // even when triggered by lifecycle interfaces like BeanFactoryAware.
     36         //这里是对单例的循环引用的处理,单例&&允许循环依赖&&正在被创建同时满足,才为true
     37         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
     38                 isSingletonCurrentlyInCreation(beanName));
     39         if (earlySingletonExposure) {
     40             if (logger.isDebugEnabled()) {
     41                 logger.debug("Eagerly caching bean '" + beanName +
     42                         "' to allow for resolving potential circular references");
     43             }
     44             addSingletonFactory(beanName, new ObjectFactory<Object>() {
     45                 @Override
     46                 public Object getObject() throws BeansException {
     47                     return getEarlyBeanReference(beanName, mbd, bean);
     48                 }
     49             });
     50         }
     51 
     52         //这里是对bean的初始化,依赖注入往往是在这里进行的,这个exposedObject在初始化完成之后会作为依赖注入完成之后的Bean
     53         // Initialize the bean instance.
     54         Object exposedObject = bean;
     55         try {
     56             //属性的填充
     57             populateBean(beanName, mbd, instanceWrapper);
     58             if (exposedObject != null) {
     59                 exposedObject = initializeBean(beanName, exposedObject, mbd);
     60             }
     61         }
     62         catch (Throwable ex) {
     63             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
     64                 throw (BeanCreationException) ex;
     65             }
     66             else {
     67                 throw new BeanCreationException(
     68                         mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
     69             }
     70         }
     71 
     72         if (earlySingletonExposure) {
     73             Object earlySingletonReference = getSingleton(beanName, false);
     74             if (earlySingletonReference != null) {
     75                 if (exposedObject == bean) {
     76                     exposedObject = earlySingletonReference;
     77                 }
     78                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
     79                     String[] dependentBeans = getDependentBeans(beanName);
     80                     Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
     81                     for (String dependentBean : dependentBeans) {
     82                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
     83                             actualDependentBeans.add(dependentBean);
     84                         }
     85                     }
     86                     if (!actualDependentBeans.isEmpty()) {
     87                         throw new BeanCurrentlyInCreationException(beanName,
     88                                 "Bean with name '" + beanName + "' has been injected into other beans [" +
     89                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
     90                                 "] in its raw version as part of a circular reference, but has eventually been " +
     91                                 "wrapped. This means that said other beans do not use the final version of the " +
     92                                 "bean. This is often the result of over-eager type matching - consider using " +
     93                                 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
     94                     }
     95                 }
     96             }
     97         }
     98 
     99         // Register bean as disposable.
    100         try {
    101             registerDisposableBeanIfNecessary(beanName, bean, mbd);
    102         }
    103         catch (BeanDefinitionValidationException ex) {
    104             throw new BeanCreationException(
    105                     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    106         }
    107 
    108         return exposedObject;
    109     }

      对于bean的创建,IOC容器其实是采用反射和cglib技术来生成的,我们可以跟踪一下createBeanInstance方法:

     1 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
     2         // Make sure bean class is actually resolved at this point.
     3         Class<?> beanClass = resolveBeanClass(mbd, beanName);
     4 
     5         if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
     6             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     7                     "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
     8         }
     9 
    10         //使用工厂方法对Bean进行实例化
    11         if (mbd.getFactoryMethodName() != null)  {
    12             return instantiateUsingFactoryMethod(beanName, mbd, args);
    13         }
    14 
    15         // Shortcut when re-creating the same bean...
    16         boolean resolved = false;
    17         boolean autowireNecessary = false;
    18         if (args == null) {
    19             synchronized (mbd.constructorArgumentLock) {
    20                 if (mbd.resolvedConstructorOrFactoryMethod != null) {
    21                     resolved = true;
    22                     autowireNecessary = mbd.constructorArgumentsResolved;
    23                 }
    24             }
    25         }
    26         if (resolved) {
    27             if (autowireNecessary) {
    28                 return autowireConstructor(beanName, mbd, null, null);
    29             }
    30             else {
    31                 return instantiateBean(beanName, mbd);
    32             }
    33         }
    34 
    35         //使用构造函数对Bean实例化
    36         // Need to determine the constructor...
    37         Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    38         if (ctors != null ||
    39                 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
    40                 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
    41             return autowireConstructor(beanName, mbd, ctors, args);
    42         }
    43 
    44         //使用默认的构造函数对Bean进行实例化
    45         // No special handling: simply use no-arg constructor.
    46         return instantiateBean(beanName, mbd);
    47     }

      1、如果指定了工厂方法,则使用工厂进行创建;

      2、如果没有指定工厂方法,则看有没指定某个构造器进行实例化;

      3、都没有,则采用默认的构造器进行实例化。进入默认的构造器方法:

     1 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
     2         try {
     3             Object beanInstance;
     4             final BeanFactory parent = this;
     5             if (System.getSecurityManager() != null) {
     6                 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
     7                     @Override
     8                     public Object run() {
     9                         return getInstantiationStrategy().instantiate(mbd, beanName, parent);
    10                     }
    11                 }, getAccessControlContext());
    12             }
    13             else {
    14                 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
    15             }
    16             BeanWrapper bw = new BeanWrapperImpl(beanInstance);
    17             initBeanWrapper(bw);
    18             return bw;
    19         }
    20         catch (Throwable ex) {
    21             throw new BeanCreationException(
    22                     mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    23         }
    24     }

      虽然getInstantiationStrategy()方法获取的是CglibSubclassingInstantiationStrategy实例,但是CglibSubclassingInstantiationStrategy中只有一个instantiate带一个参数和一个可变参数的方法,和这里调用的并不是同一个方法,所以,这里调用的是它的父类SimpleInstantiationStrategy中的instantiate方法,进入:

     1 public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
     2         // Don't override the class with CGLIB if no overrides.
     3         if (bd.getMethodOverrides().isEmpty()) {
     4             Constructor<?> constructorToUse;
     5             synchronized (bd.constructorArgumentLock) {
     6                 //这里取得指定的构造器或者生产对象的工厂方法来对Bean进行实例化
     7                 constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
     8                 if (constructorToUse == null) {
     9                     final Class<?> clazz = bd.getBeanClass();
    10                     if (clazz.isInterface()) {
    11                         throw new BeanInstantiationException(clazz, "Specified class is an interface");
    12                     }
    13                     try {
    14                         if (System.getSecurityManager() != null) {
    15                             constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
    16                                 @Override
    17                                 public Constructor<?> run() throws Exception {
    18                                     return clazz.getDeclaredConstructor((Class[]) null);
    19                                 }
    20                             });
    21                         }
    22                         else {
    23                             constructorToUse =    clazz.getDeclaredConstructor((Class[]) null);
    24                         }
    25                         bd.resolvedConstructorOrFactoryMethod = constructorToUse;
    26                     }
    27                     catch (Throwable ex) {
    28                         throw new BeanInstantiationException(clazz, "No default constructor found", ex);
    29                     }
    30                 }
    31             }
    32             //使用反射进行实例化
    33             return BeanUtils.instantiateClass(constructorToUse);
    34         }
    35         else {
    36             //使用cglb进行实例化
    37             // Must generate CGLIB subclass.
    38             return instantiateWithMethodInjection(bd, beanName, owner);
    39         }
    40     }

      这段代码可以看到,IOC是使用反射和cglib来进行实例化对象的。好了,我们回到之前的方法,到populateBean(beanName, mbd, instanceWrapper)方法进行跟踪:

     1 protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
     2         //在前面解析的过程中,XML中设置的属性已经填充到beanDefinition 的propertyValues属性中
     3         PropertyValues pvs = mbd.getPropertyValues();
     4 
     5         if (bw == null) {
     6             if (!pvs.isEmpty()) {
     7                 throw new BeanCreationException(
     8                         mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
     9             }
    10             else {
    11                 // Skip property population phase for null instance.
    12                 return;
    13             }
    14         }
    15 
    16         // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    17         // state of the bean before properties are set. This can be used, for example,
    18         // to support styles of field injection.
    19         boolean continueWithPropertyPopulation = true;
    20 
    21         if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    22             for (BeanPostProcessor bp : getBeanPostProcessors()) {
    23                 if (bp instanceof InstantiationAwareBeanPostProcessor) {
    24                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    25                     if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
    26                         continueWithPropertyPopulation = false;
    27                         break;
    28                     }
    29                 }
    30             }
    31         }
    32 
    33         if (!continueWithPropertyPopulation) {
    34             return;
    35         }
    36 
    37         //开始进行依赖注入的操作
    38         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
    39                 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    40             MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    41 
    42             //按属性的名字来进行注入
    43             // Add property values based on autowire by name if applicable.
    44             if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
    45                 autowireByName(beanName, mbd, bw, newPvs);
    46             }
    47 
    48             //按属性的类型来进行注入
    49             // Add property values based on autowire by type if applicable.
    50             if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    51                 autowireByType(beanName, mbd, bw, newPvs);
    52             }
    53 
    54             pvs = newPvs;
    55         }
    56 
    57         boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    58         boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    59 
    60         if (hasInstAwareBpps || needsDepCheck) {
    61             PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    62             if (hasInstAwareBpps) {
    63                 for (BeanPostProcessor bp : getBeanPostProcessors()) {
    64                     if (bp instanceof InstantiationAwareBeanPostProcessor) {
    65                         InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
    66                         pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
    67                         if (pvs == null) {
    68                             return;
    69                         }
    70                     }
    71                 }
    72             }
    73             if (needsDepCheck) {
    74                 checkDependencies(beanName, mbd, filteredPds, pvs);
    75             }
    76         }
    77 
    78         //对属性进行注入
    79         applyPropertyValues(beanName, mbd, bw, pvs);
    80     }

      可以看到:

      1、我们可以在XML中指定autowired的值,是按名称还是类型来进行注入;

      2、真正进行属性注入的是applyPropertyValues方法,进入:

     1 protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
     2         if (pvs == null || pvs.isEmpty()) {
     3             return;
     4         }
     5 
     6         if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
     7             ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
     8         }
     9 
    10         MutablePropertyValues mpvs = null;
    11         List<PropertyValue> original;
    12 
    13         if (pvs instanceof MutablePropertyValues) {
    14             mpvs = (MutablePropertyValues) pvs;
    15             if (mpvs.isConverted()) {
    16                 // Shortcut: use the pre-converted values as-is.
    17                 try {
    18                     bw.setPropertyValues(mpvs);
    19                     return;
    20                 }
    21                 catch (BeansException ex) {
    22                     throw new BeanCreationException(
    23                             mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    24                 }
    25             }
    26             original = mpvs.getPropertyValueList();
    27         }
    28         else {
    29             original = Arrays.asList(pvs.getPropertyValues());
    30         }
    31 
    32         TypeConverter converter = getCustomTypeConverter();
    33         if (converter == null) {
    34             converter = bw;
    35         }
    36         //获取解析器
    37         BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
    38 
    39         // Create a deep copy, resolving any references for values.
    40         List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
    41         boolean resolveNecessary = false;
    42         for (PropertyValue pv : original) {
    43             //如果已经转换过,就直接存入
    44             if (pv.isConverted()) {
    45                 deepCopy.add(pv);
    46             }
    47             else {
    48                 //获取属性名称
    49                 String propertyName = pv.getName();
    50                 //获取属性值
    51                 Object originalValue = pv.getValue();
    52                 //将值进行转换,比如属性的值有可能是数组、集合,或者对象,并且该对象也需要进行属性的注入,
    53                 //那么还会进行递归调用getBean方法,将该对象生成好之后再注入给当前的属性
    54                 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
    55                 Object convertedValue = resolvedValue;
    56                 boolean convertible = bw.isWritableProperty(propertyName) &&
    57                         !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
    58                 if (convertible) {
    59                     convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
    60                 }
    61                 // Possibly store converted value in merged bean definition,
    62                 // in order to avoid re-conversion for every created bean instance.
    63                 if (resolvedValue == originalValue) {
    64                     if (convertible) {
    65                         pv.setConvertedValue(convertedValue);
    66                     }
    67                     deepCopy.add(pv);
    68                 }
    69                 else if (convertible && originalValue instanceof TypedStringValue &&
    70                         !((TypedStringValue) originalValue).isDynamic() &&
    71                         !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
    72                     pv.setConvertedValue(convertedValue);
    73                     deepCopy.add(pv);
    74                 }
    75                 else {
    76                     resolveNecessary = true;
    77                     deepCopy.add(new PropertyValue(pv, convertedValue));
    78                 }
    79             }
    80         }
    81         if (mpvs != null && !resolveNecessary) {
    82             mpvs.setConverted();
    83         }
    84 
    85         //设置依赖注入的地方
    86         // Set our (possibly massaged) deep copy.
    87         try {
    88             bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    89         }
    90         catch (BeansException ex) {
    91             throw new BeanCreationException(
    92                     mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    93         }
    94     }

      至此,一个完整的bean就算创建完成了,要用的时候,直接找IOC容器拿就行了。

  • 相关阅读:
    Octave中的函数记录
    利用jira-python对jira项目
    通过python中xlrd读取excel表格(xlwt写入excel),xlsxwriter写入excel表格并绘制图形
    使用python的requests模块采集请求中的数据
    react+webpack+webstorm开发环境搭建
    Django中url使用总结
    通过Django中的forms类对前台的forms表单数据进行校验
    4.软件测试用例设计
    3.软件开发与测试模型
    16 IO流
  • 原文地址:https://www.cnblogs.com/helei123/p/11117361.html
Copyright © 2011-2022 走看看