zoukankan      html  css  js  c++  java
  • 【spring源码分析】IOC容器初始化(八)

    • 前言:在上文bean加载过程中还要一个非常重要的方法没有分析createBean,该方法非常重要,因此特意提出来单独分析。

    createBean方法定义在AbstractBeanFactory中:

    该方法根据给定的beanName、BeanDefinition和args实例化一个bean对象。所有bean实例的创建都会委托给该方法实现。

    AbstractAutowireCapableBeanFactory#createBean

    createBean的默认实现在AbstractAutowireCapableBeanFactory类中,代码如下:

     1 protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
     2             throws BeanCreationException {
     3         if (logger.isDebugEnabled()) {
     4             logger.debug("Creating instance of bean '" + beanName + "'");
     5         }
     6         RootBeanDefinition mbdToUse = mbd;
     7 
     8         // Make sure bean class is actually resolved at this point, and
     9         // clone the bean definition in case of a dynamically resolved Class
    10         // which cannot be stored in the shared merged bean definition.
    11         // 确保此时的bean已经被解析了
    12         // 如果获取的class属性不为null,则克隆该BeanDefinition,主要是因为动态解析的class无法保存到共享的BeanDefinition
    13         Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    14         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    15             mbdToUse = new RootBeanDefinition(mbd);
    16             mbdToUse.setBeanClass(resolvedClass);
    17         }
    18 
    19         // Prepare method overrides.
    20         try {
    21             // 验证和准备覆盖方法
    22             mbdToUse.prepareMethodOverrides();
    23         } catch (BeanDefinitionValidationException ex) {
    24             throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    25                                                    beanName, "Validation of method overrides failed", ex);
    26         }
    27 
    28         try {
    29             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    30             // 实例化的前置处理
    31             // 给BeanPostProcessor一个机会用来返回一个代理类而不是真正的实例类
    32             // AOP的功能就是基于这个地方
    33             Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    34             if (bean != null) {
    35                 return bean;
    36             }
    37         } catch (Throwable ex) {
    38             throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
    39                                             "BeanPostProcessor before instantiation of bean failed", ex);
    40         }
    41 
    42         try {
    43             // 创建Bean对象
    44             Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    45             if (logger.isDebugEnabled()) {
    46                 logger.debug("Finished creating instance of bean '" + beanName + "'");
    47             }
    48             return beanInstance;
    49         } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
    50             // A previously detected exception with proper bean creation context already,
    51             // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
    52             throw ex;
    53         } catch (Throwable ex) {
    54             throw new BeanCreationException(
    55                     mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    56         }
    57     }

    分析:

    • 通过resolveBeanClass解析BeanDefinition的class属性。
    • 处理override属性。
    • 通过resolveBeforeInstantiation进行实例化的前置处理。
    • 最后通过doCreateBean创建bean对象。

    AbstractBeanFactory#resolveBeanClass

     1 protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
     2             throws CannotLoadBeanClassException {
     3 
     4         try {
     5             if (mbd.hasBeanClass()) {
     6                 return mbd.getBeanClass();
     7             }
     8             if (System.getSecurityManager() != null) {
     9                 return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
    10                         doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
    11             } else {
    12                 return doResolveBeanClass(mbd, typesToMatch);
    13             }
    14         // ..... 省略异常处理
    15     }

    分析:

    该方法主要是解析BeanDefinition的class类,如果解析的class类不为空,则将其设置到mbdToUse中,因为动态解析的class无法保存到共享的BeanDefinition中。

    AbstractBeanFactory#prepareMethodOverrides

     1 public void prepareMethodOverrides() throws BeanDefinitionValidationException {
     2         // Check that lookup methods exists.
     3         // 如果方法可以覆盖
     4         if (hasMethodOverrides()) {
     5             // 得到覆盖方法
     6             Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
     7             // 同步
     8             synchronized (overrides) {
     9                 // 循环调用 prepareMethodOverride进行覆盖准备
    10                 for (MethodOverride mo : overrides) {
    11                     prepareMethodOverride(mo);
    12                 }
    13             }
    14         }
    15     }

    分析:

    bean标签中的lookup-method和replace-method属性就是放在BeanDefinition的methodOverrides属性中(关于这两个属性的分析后续再来分析),这里就是对methodOverrides属性进行处理,动态为当前bean生产代理并使用对应的拦截器为bean做增强处理。

    上述处理逻辑就是循环获取MethodOverride属性,然后调用prepareMethodOverride进行处理。

     1 // AbstractBeanDefinition
     2 protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
     3         int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
     4         if (count == 0) {
     5             throw new BeanDefinitionValidationException(
     6                     "Invalid method override: no method with name '" + mo.getMethodName() +
     7                             "' on class [" + getBeanClassName() + "]");
     8         } else if (count == 1) {
     9             // Mark override as not overloaded, to avoid the overhead of arg type checking.
    10             mo.setOverloaded(false);
    11         }
    12     }

    分析:

    根据方法名,从class中获取该方法名的个数:

    • 如果方法名个数为0,则抛出BeanDefinitionValidationException异常,原因其实很简单:通过方法名去查找,而又没有找到,则说明有问题,抛出异常。
    • 如果方法名个数为1,则设置该方法未被重载(overloaded属性模式为true)。如果一个类存在多个重载方法,在方法调用的时候还需根据参数类型来判断到底重载的是哪个方法,这里通过count=1,来表示该方法未被重载,在调用的时候可以直接找方法而不需要进行方法参数的校验,相当于一个小小的优化,提升后面调用函数的速度。

    AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation

     1 protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
     2         Object bean = null;
     3         // 如果bean不是应用系统的,有BeanPostProcessor
     4         if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
     5             // Make sure bean class is actually resolved at this point.
     6             if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
     7                 Class<?> targetType = determineTargetType(beanName, mbd);
     8                 if (targetType != null) {
     9                     // 前置处理
    10                     bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    11                     if (bean != null) {
    12                         // 后置处理
    13                         bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    14                     }
    15                 }
    16             }
    17             mbd.beforeInstantiationResolved = (bean != null);
    18         }
    19         return bean;
    20     }

    分析:

    通过applyBeanPostProcessorsBeforeInstantiation和applyBeanPostProcessorsAfterInitialization对bean实例化前进行前置与后置处理。如果返回了代理对象,则直接返回结果,Spring后续实现AOP就是基于这个地方进行的判断。

    前置处理与后置处理后续再具体进行分析。

    AbstractAutowireCapableBeanFactory#doCreateBean

      1 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      2             throws BeanCreationException {
      3 
      4         // Instantiate the bean.
      5         // BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象、获取被包装bean的属性描述器
      6         BeanWrapper instanceWrapper = null;
      7         // 如果是单例模型,则从未完成的FactoryBean缓存中删除
      8         if (mbd.isSingleton()) {
      9             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
     10         }
     11         // 使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
     12         if (instanceWrapper == null) {
     13             instanceWrapper = createBeanInstance(beanName, mbd, args);
     14         }
     15         // 包装的对象实例
     16         final Object bean = instanceWrapper.getWrappedInstance();
     17         // 包装的实例对象的类型
     18         Class<?> beanType = instanceWrapper.getWrappedClass();
     19         if (beanType != NullBean.class) {
     20             mbd.resolvedTargetType = beanType;
     21         }
     22 
     23         // Allow post-processors to modify the merged bean definition.
     24         // 先做同步,然后判断是否有后置处理
     25         synchronized (mbd.postProcessingLock) {
     26             if (!mbd.postProcessed) {
     27                 try {
     28                     // 后置处理修改BeanDefinition
     29                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
     30                 } catch (Throwable ex) {
     31                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     32                                                     "Post-processing of merged bean definition failed", ex);
     33                 }
     34                 mbd.postProcessed = true;
     35             }
     36         }
     37 
     38         // Eagerly cache singletons to be able to resolve circular references
     39         // even when triggered by lifecycle interfaces like BeanFactoryAware.
     40         // 解决单例模式的循环依赖         // 单例模式               运行循环依赖
     41         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
     42                 isSingletonCurrentlyInCreation(beanName));// 当前单例bean是否正在被创建
     43         if (earlySingletonExposure) {
     44             if (logger.isDebugEnabled()) {
     45                 logger.debug("Eagerly caching bean '" + beanName +
     46                                      "' to allow for resolving potential circular references");
     47             }
     48             // 提前将创建的bean实例加入到singletonFactories中
     49             // 为了后期避免循环依赖
     50             addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
     51         }
     52 
     53         // Initialize the bean instance.
     54         // 开始初始化bean实例对象
     55         Object exposedObject = bean;
     56         try {
     57             // 对bean进行填充,主要是进行属性注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖bean
     58             populateBean(beanName, mbd, instanceWrapper);
     59             // 进行bean初始化
     60             exposedObject = initializeBean(beanName, exposedObject, mbd);
     61         } catch (Throwable ex) {
     62             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
     63                 throw (BeanCreationException) ex;
     64             } else {
     65                 throw new BeanCreationException(
     66                         mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
     67             }
     68         }
     69 
     70         // 循环依赖处理
     71         if (earlySingletonExposure) {
     72             // 获取earlySingletonReference
     73             Object earlySingletonReference = getSingleton(beanName, false);
     74             // 只有在循环依赖的情况下,earlySingletonReference才不会为null
     75             if (earlySingletonReference != null) {
     76                 // 如果exposedObject没有在初始化方法中改变,也就是没有被增强
     77                 if (exposedObject == bean) {
     78                     exposedObject = earlySingletonReference;
     79                 } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { // 处理依赖
     80                     String[] dependentBeans = getDependentBeans(beanName);
     81                     Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
     82                     for (String dependentBean : dependentBeans) {
     83                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
     84                             actualDependentBeans.add(dependentBean);
     85                         }
     86                     }
     87                     if (!actualDependentBeans.isEmpty()) {
     88                         throw new BeanCurrentlyInCreationException(beanName,
     89                                                                    "Bean with name '" + beanName + "' has been injected into other beans [" +
     90                                                                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
     91                                                                            "] in its raw version as part of a circular reference, but has eventually been " +
     92                                                                            "wrapped. This means that said other beans do not use the final version of the " +
     93                                                                            "bean. This is often the result of over-eager type matching - consider using " +
     94                                                                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
     95                     }
     96                 }
     97             }
     98         }
     99 
    100         // Register bean as disposable.
    101         try {
    102             // 注册bean
    103             registerDisposableBeanIfNecessary(beanName, bean, mbd);
    104         } catch (BeanDefinitionValidationException ex) {
    105             throw new BeanCreationException(
    106                     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    107         }
    108 
    109         return exposedObject;
    110     }

    分析:

    如果没有代理对象,则会进行bean对象的创建。

    • 如果BeanDefinition为单例模式,首先从FactoryBean缓存中删除该beanName的缓存。
    • 调用createBeanInstance方法创建一个BeanWrapper对象。
    • 调用applyMergedBeanDefinitionPostProcessors对BeanDefinition进行后置处理
    • 进行单例模式的循环依赖处理。
    • 调用populateBean进行bean属性填充。
    • 调用initializeBean进行bean初始化。
    • 进行依赖检查。
    • 最后注册bean。

    上述列出了创建bean对象的主要步骤,过程还是比较复杂的,下面一一进行分析。主要关注点createBeanInstance、populateBean、initializeBean三个函数。

    AbstractAutowireCapableBeanFactory#createBeanInstance

     1 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
     2         // Make sure bean class is actually resolved at this point.
     3         // 解析bean,将bean类名解析为class引用
     4         Class<?> beanClass = resolveBeanClass(mbd, beanName);
     5 
     6         if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
     7             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     8                                             "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
     9         }
    10 
    11         // 如果存在supplier回调,则使用给定的回调方法初始化策略
    12         Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    13         if (instanceSupplier != null) {
    14             return obtainFromSupplier(instanceSupplier, beanName);
    15         }
    16 
    17         // 使用FactoryBean的factor-method来创建bean,支持静态工厂和实例工厂
    18         if (mbd.getFactoryMethodName() != null) {
    19             return instantiateUsingFactoryMethod(beanName, mbd, args);
    20         }
    21 
    22         // Shortcut when re-creating the same bean...
    23         boolean resolved = false;
    24         boolean autowireNecessary = false;
    25         if (args == null) {
    26             // 做同步
    27             synchronized (mbd.constructorArgumentLock) {
    28                 // 如果已缓存的解析构造函数或者工厂方法不为null,则可以利用构造函数解析
    29                 // 因为需要根据参数确认到底使用哪个构造函数,该过程比较消耗性能,所以采用缓存机制
    30                 if (mbd.resolvedConstructorOrFactoryMethod != null) {
    31                     resolved = true;
    32                     autowireNecessary = mbd.constructorArgumentsResolved;
    33                 }
    34             }
    35         }
    36         // 已经解析好了,直接注入即可
    37         if (resolved) {
    38             // autowire自动注入,调用构造函数自动注入
    39             if (autowireNecessary) {
    40                 return autowireConstructor(beanName, mbd, null, null);
    41             } else {
    42                 // 使用默认构造函数构造
    43                 return instantiateBean(beanName, mbd);
    44             }
    45         }
    46 
    47         // Need to determine the constructor...
    48         // 确定解析的构造函数
    49         // 主要是检查已经注册的SmartInstantiationAwareBeanPostProcessor
    50         Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    51         // 确定构造方法进行bean创建
    52         if (ctors != null ||
    53                 mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
    54                 mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    55             return autowireConstructor(beanName, mbd, ctors, args);
    56         }
    57 
    58         // 有参数,又没有获取到构造方法,则只能调用无参构造方法来创建实例
    59         // 这是一个兜底的方法
    60         // No special handling: simply use no-arg constructor.
    61         return instantiateBean(beanName, mbd);
    62     }

    分析:

    bean的实例化一个比较复杂的过程。

    • 如果设置Supplier回调,则调用obtainFromSupplier方法进行初始化。
    • 如果存在工厂方法,则使用工厂方法进行初始化。
    • 先判断缓存中是否存在构造函数,如果存在,则根据是否使用自动注入,还是默认的构造函数进行bean对象的初始化。
    • 如果缓存中不存在,则需先判断到底使用哪个构造函数来完成解析工作。
    • 如果上述条件还是不满足,则使用无参构造方法来创建实例。

    #1.如果设置Supplier回调,则使用obtainFromSupplier方法进行初始化。

    首先了解下Supplier接口(java.util.function)

    • Supplier接口仅有一个功能性的get()方法,该方法会返回一个<T>类型的对象,有点类似工厂方法。
    • 如果我们在创建BeanDefinition的时候设置了Supplier参数,那么其他的构造器或者工厂方法就没有作用了。
    • AbstractBeanDefinition中提供了设置Supplier的入口:

    AbstractAutowireCapableBeanFactory#obtainFromSupplier

     1 protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
     2         // 获得原创建的Bean的对象名
     3         String outerBean = this.currentlyCreatedBean.get();
     4         // 设置新的Bean对象名到currentlyCreatedBean中
     5         this.currentlyCreatedBean.set(beanName);
     6         Object instance;
     7         try {
     8             // 调用Supplier的get(),返回一个Bean对象
     9             instance = instanceSupplier.get();
    10         } finally {
    11             // 设置原创建的Bean对象名到currentlyCreatedBean中
    12             if (outerBean != null) {
    13                 this.currentlyCreatedBean.set(outerBean);
    14             } else {
    15                 this.currentlyCreatedBean.remove();
    16             }
    17         }
    18         // 创建BeanWrapper对象
    19         BeanWrapper bw = new BeanWrapperImpl(instance);
    20         // 初始化BeanWrapper
    21         initBeanWrapper(bw);
    22         return bw;
    23     }

    分析:

    • 调用Supplier#get方法,获取一个Bean实例对象。
    • 根据该实例对象构建BeanWrapper对象。
    • 最后初始化该对象。

    如果存在工厂方法,则会调用工厂方法来完成bean的初始化工作,该方法实现比较长,并且细节复杂,由于篇幅原因放在下篇文章中解析。

    总结

    这里仅仅分析了doCreateBean方法中的一点点内容,如果存在Supplier回调,则会直接通过Supplier来创建Bean对象,构造函数和工厂方法则失效,下面将对分析使用工厂方法实例化Bean对象的过程。


    by Shawn Chen,2019.04.23,下午。

  • 相关阅读:
    iframe与动作连处理
    selenium其他自动化操作
    使用seleniun模拟登陆qq空间
    selenium基本使用
    验证码识别 云打码之古诗文网验证识别
    图片爬取基础
    centos8下LAMP搭建Nextcloud
    浅谈centos8与centos7
    DHCP服务器配置及测试
    使用Apache服务器实现Nginx反向代理
  • 原文地址:https://www.cnblogs.com/developer_chan/p/10750950.html
Copyright © 2011-2022 走看看