SpringloC容器的依赖注入源码解析(5)—— doCreateBean之创建无属性的bean

本文阅读 5 分钟
首页 代码,Java 正文

img 上一篇文章分析到createBean执行到了doCreateBean方法: img 自定义的WelcomeController下面有一个成员变量WelcomeService被@Autowired标签标记

进入到doCreateBean方法里:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException { 

   // Instantiate the bean.
   // bean实例包装类
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) { 
      // 从未完成创建的包装Bean缓存中清理并获取相关中的包装Bean实例,毕竟是单例的,只能存一份
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) { 
      //创建bean的时候,这里创建bean的实例有三种方法
      // 1.工厂方法创建
      // 2.构造方法的方式注入
      // 3.无参构造方法注入
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   final Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) { 
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   // 调用BeanDefinition属性合并完成后的BeanPostProcessor后置处理器
   synchronized (mbd.postProcessingLock) { 
      if (!mbd.postProcessed) { 
         try { 
            // 被@Autowired、@Value标记的属性在这里获取
            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.
   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 " +
                     "'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;
}

首先定义了一个包装类BeanWrapper, img 该接口是spring提供的用于操作bean中属性的工具,使用它可以直接修改bean里面的属性, img BeanWrapperImpl是AbstractNestablePropertyAccessor的子类,BeanWrapper的实现类,通过父类使得其具有处理属性的能力。

回到doCreateBean,接下来判断BeanDefinition是否是单例,如果是的话尝试从缓存中获取FactoryBean实例,如果获取不到就会执行

instanceWrapper = createBeanInstance(beanName, mbd, args);

进入到createBeanInstance里:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) { 
   // Make sure bean class is actually resolved at this point.
   Class<?> beanClass = resolveBeanClass(mbd, beanName);
   // 检查是否有权通过反射创建private的Class
   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.
   // 使用默认的构造函数
   return instantiateBean(beanName, mbd);
}

第一行会再次调用resolveBeanClass尝试去获取bean里面的class对象,之后看看class的访问修饰符,检查是否有权通过反射创建private的Class,如果bean使用了java自带的函数式接口Supplier,即工厂方法,就会调用工厂方法里的get方法来创建bean实例

@FunctionalInterface
public interface Supplier<T> { 

    /** * Gets a result. * * @return a result */
    T get();
}

这里我们没有用到Supplier,就会看一下BeanDefinition里有没有定义Spring里的工厂方法,如果有则通过factory-method来返回实例。

如果不是上述两种方式,如果传入的args参数为空就会来到synchronized代码块,先判断一下先前解析配置成BeanDefinition实例的时候,有没有获取到已经解析的构造函数,如果有就会调用

return autowireConstructor(beanName, mbd, null, null);

进行有参构造函数的解析。

之后会使用带参的构造函数进行装配或者无参的构造函数进行装配。

return instantiateBean(beanName, mbd);

进入到调用无参构造函数的方法里:

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { 
   try { 
      Object beanInstance;
      final BeanFactory parent = this;
      if (System.getSecurityManager() != null) { 
         beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
               getInstantiationStrategy().instantiate(mbd, beanName, parent),
               getAccessControlContext());
      }
      else { 
         //使用指定的策路模式来初始化实例,默认用的是SimplelnstantiationStrategy的cglib方法
         beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
      }
      BeanWrapper bw = new BeanWrapperImpl(beanInstance);
      initBeanWrapper(bw);
      return bw;
   }
   catch (Throwable ex) { 
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
   }
}

instantiate默认调用的是SimpleInstantiationStrategy类中的方法,在方法里会首先判断是否有look-up method等使用其他bean的替换方法的情况,如果有的话会使用cglib重写bean原本的方法,没有的话会制定同步代码块

@Override
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) { 
   // Don't override the class with CGLIB if no overrides.
   // 如果Bean定义里面的方法没有被覆盖,则不需要CGLUB来重写
   if (!bd.hasMethodOverrides()) { 
      Constructor<?> constructorToUse;
      synchronized (bd.constructorArgumentLock) { 
         // 获取对象的构造方法或工厂方法
         constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
         if (constructorToUse == null) { 
            //使 用反射机制获取Bean的类,看看是否是接口
            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(
                        (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
               }
               else { 
                  constructorToUse = clazz.getDeclaredConstructor();
               }
               bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            }
            catch (Throwable ex) { 
               throw new BeanInstantiationException(clazz, "No default constructor found", ex);
            }
         }
      }
      // 使用BeanUtils,最终调用newInstance方法通过反射来获取实例
      return BeanUtils.instantiateClass(constructorToUse);
   }
   else { 
      // Must generate CGLIB subclass.
      return instantiateWithMethodInjection(bd, beanName, owner);
   }
}

再回到instantiateBean方法,获取到了创建好的bean实例之后,就会将其包装到BeanWrapper里,包装好了之后还回去初始化 img

protected void initBeanWrapper(BeanWrapper bw) { 
   bw.setConversionService(getConversionService());
   registerCustomEditors(bw);
}

initBeanWrapper主要是给wrapper设定上自定义类型转换工具

instantiateBean最终创建好的beanWrapper,此时就完成了createBeanInstance的调用。

回到doCreateBean,此时就会将创建好的instanceWrapper的bean实例类型传入到applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://wangjiawei.blog.csdn.net/article/details/121432546
-- 展开阅读全文 --
安全面试之XSS(跨站脚本攻击)
« 上一篇 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复