zoukankan      html  css  js  c++  java
  • spring源码解析之IOC容器(三)——依赖注入

      上一篇主要是跟踪了IOC容器对bean标签进行解析之后存入Map中的过程,这些bean只是以BeanDefinition为载体单纯的存储起来了,并没有转换成一个个的对象,今天继续进行跟踪,看一看IOC容器是怎样实例化对象的。

      我们都使用过以下代码:

    1 FileSystemXmlApplicationContext  context=new FileSystemXmlApplicationContext("bean.xml");
    2 User user=context.getBean("user",User.class);

      这样我们就能获取到user对象了,所以,不难想象,这个getBean方法就是实例化对象的入口。接下来我们就以这个方法为切入点,来探究IOC容器中bean的实例化过程。getBean方法是在FileSystemXmlApplicationContext的基类AbstractApplicationContext中定义的,代码如下:

    1 public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    2         assertBeanFactoryActive();
    3         return getBeanFactory().getBean(name, requiredType);
    4     }

      里面有很多重载方法,里面有调用了某个beanFactory的getBean方法。AbstractApplicationContext中并没有定义getBeanFactory这个方法,那一定是在FileSystemXmlApplicatio

    —ntext的某个父类中定义的,我们再回过头看一下它的UML图:

      经过查找之后,是在AbstractRefreshableApplicationContext中定义的,且这个beanFactory是DefaultListableBeanFactory类型的:

     1 public abstract class AbstractRefreshableApplicationContext extends AbstractApplicationContext {
     2 
     3     private Boolean allowBeanDefinitionOverriding;
     4 
     5     private Boolean allowCircularReferences;
     6 
     7     /** Bean factory for this context */
     8     private DefaultListableBeanFactory beanFactory;
     9 
    10     /** Synchronization monitor for the internal BeanFactory */
    11     private final Object beanFactoryMonitor = new Object();

      直接进入DefaultListableBeanFactory中,查看它的getBean方法:

    public <T> T getBean(Class<T> requiredType) throws BeansException {
            return getBean(requiredType, (Object[]) null);
        }
    public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
            NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);
            if (namedBean != null) {
                return namedBean.getBeanInstance();
            }
            BeanFactory parent = getParentBeanFactory();
            if (parent != null) {
                return parent.getBean(requiredType, args);
            }
            throw new NoSuchBeanDefinitionException(requiredType);
        }

      发现里面只有这两个重载方法,其他getBean方法,包括例子中使用的那个重载方法没有看到,我们看一下DefaultListableBeanFactory类的UML图:

      经查找,发现在父类AbstractBeanFactory中定义了其他的getBean方法,如下:

    1 public Object getBean(String name, Object... args) throws BeansException {
    2         return doGetBean(name, null, args, false);
    3     }
    1 public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
    2         return doGetBean(name, requiredType, args, false);
    3     }

      里面都调用了doGetBean方法,那么进入继续跟踪:

      1 protected <T> T doGetBean(
      2             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
      3             throws BeansException {
      4         //将bean的name进行转换,比如将name前面的“&”符去掉,带“&”的name,获取的是beanFactory本身,而不是
      5         //beanFactory生成出来的bean实例
      6         final String beanName = transformedBeanName(name);
      7         Object bean;
      8 
      9         // Eagerly check singleton cache for manually registered singletons.
     10         //看缓存中是否已经有该bean
     11         Object sharedInstance = getSingleton(beanName);
     12         //如果缓存中有
     13         if (sharedInstance != null && args == null) {
     14             if (logger.isDebugEnabled()) {
     15                 if (isSingletonCurrentlyInCreation(beanName)) {
     16                     logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
     17                             "' that is not fully initialized yet - a consequence of a circular reference");
     18                 }
     19                 else {
     20                     logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
     21                 }
     22             }
     23             //如果sharedInstance是FactoryBean类型,则返回它生产的对象,否则,返回它本身
     24             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
     25         }
     26         //如果缓存中没有,第一次创建的时候
     27         else {
     28             // Fail if we're already creating this bean instance:
     29             // We're assumably within a circular reference.
     30             if (isPrototypeCurrentlyInCreation(beanName)) {
     31                 throw new BeanCurrentlyInCreationException(beanName);
     32             }
     33 
     34             // Check if bean definition exists in this factory.
     35             //获取父容器
     36             BeanFactory parentBeanFactory = getParentBeanFactory();
     37             //如果父容器存在,且在当前容器中没有找到该名称的bean的数据
     38             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
     39                 //则到父容器中进行处理
     40                 // Not found -> check parent.
     41                 //将name前加上“&”
     42                 String nameToLookup = originalBeanName(name);
     43                 //分别对是否有参数的情况进行处理
     44                 if (args != null) {
     45                     // Delegation to parent with explicit args.
     46                     return (T) parentBeanFactory.getBean(nameToLookup, args);
     47                 }
     48                 else {
     49                     // No args -> delegate to standard getBean method.
     50                     return parentBeanFactory.getBean(nameToLookup, requiredType);
     51                 }
     52             }
     53 
     54             if (!typeCheckOnly) {
     55                 markBeanAsCreated(beanName);
     56             }
     57 
     58             try {
     59                 //将数据封装成RootBeanDefinition对象
     60                 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
     61                 //检查是否为抽象类
     62                 checkMergedBeanDefinition(mbd, beanName, args);
     63 
     64                 // Guarantee initialization of beans that the current bean depends on.
     65                 //获取当前创建的bean的依赖的bean
     66                 String[] dependsOn = mbd.getDependsOn();
     67                 if (dependsOn != null) {
     68                     for (String dep : dependsOn) {
     69                         if (isDependent(beanName, dep)) {
     70                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     71                                     "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
     72                         }
     73                         //为当前bean和它的依赖对象建立映射关系
     74                         registerDependentBean(dep, beanName);
     75                         try {
     76                             //递归调用getBean方法,创建依赖对象,直到没有依赖对象为止
     77                             getBean(dep);
     78                         }
     79                         catch (NoSuchBeanDefinitionException ex) {
     80                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
     81                                     "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
     82                         }
     83                     }
     84                 }
     85 
     86                 // Create bean instance.
     87                 if (mbd.isSingleton()) {
     88                     sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
     89                         @Override
     90                         public Object getObject() throws BeansException {
     91                             try {
     92                                 //回调方法
     93                                 return createBean(beanName, mbd, args);
     94                             }
     95                             catch (BeansException ex) {
     96                                 // Explicitly remove instance from singleton cache: It might have been put there
     97                                 // eagerly by the creation process, to allow for circular reference resolution.
     98                                 // Also remove any beans that received a temporary reference to the bean.
     99                                 destroySingleton(beanName);
    100                                 throw ex;
    101                             }
    102                         }
    103                     });
    104                     bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    105                 }
    106 
    107                 else if (mbd.isPrototype()) {
    108                     // It's a prototype -> create a new instance.
    109                     Object prototypeInstance = null;
    110                     try {
    111                         beforePrototypeCreation(beanName);
    112                         prototypeInstance = createBean(beanName, mbd, args);
    113                     }
    114                     finally {
    115                         afterPrototypeCreation(beanName);
    116                     }
    117                     bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    118                 }
    119 
    120                 else {
    121                     String scopeName = mbd.getScope();
    122                     final Scope scope = this.scopes.get(scopeName);
    123                     if (scope == null) {
    124                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
    125                     }
    126                     try {
    127                         Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
    128                             @Override
    129                             public Object getObject() throws BeansException {
    130                                 beforePrototypeCreation(beanName);
    131                                 try {
    132                                     return createBean(beanName, mbd, args);
    133                                 }
    134                                 finally {
    135                                     afterPrototypeCreation(beanName);
    136                                 }
    137                             }
    138                         });
    139                         bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
    140                     }
    141                     catch (IllegalStateException ex) {
    142                         throw new BeanCreationException(beanName,
    143                                 "Scope '" + scopeName + "' is not active for the current thread; consider " +
    144                                 "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
    145                                 ex);
    146                     }
    147                 }
    148             }
    149             catch (BeansException ex) {
    150                 cleanupAfterBeanCreationFailure(beanName);
    151                 throw ex;
    152             }
    153         }
    154 
    155         // Check if required type matches the type of the actual bean instance.
    156         if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
    157             try {
    158                 return getTypeConverter().convertIfNecessary(bean, requiredType);
    159             }
    160             catch (TypeMismatchException ex) {
    161                 if (logger.isDebugEnabled()) {
    162                     logger.debug("Failed to convert bean '" + name + "' to required type '" +
    163                             ClassUtils.getQualifiedName(requiredType) + "'", ex);
    164                 }
    165                 throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    166             }
    167         }
    168         return (T) bean;
    169     }

      可以看到对不同scope域的bean的创建过程,其中会进行递归创建,现在进入createBean方法中,其实现是在AbstractAutowireCapableBeanFactory类中,代码如下:

     1 protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
     2         if (logger.isDebugEnabled()) {
     3             logger.debug("Creating instance of bean '" + beanName + "'");
     4         }
     5         RootBeanDefinition mbdToUse = mbd;
     6 
     7         // Make sure bean class is actually resolved at this point, and
     8         // clone the bean definition in case of a dynamically resolved Class
     9         // which cannot be stored in the shared merged bean definition.
    10         //判断需要创建的bean是否可以实例化,是否可以通过类装载其进行装载
    11         Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    12         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
    13             mbdToUse = new RootBeanDefinition(mbd);
    14             mbdToUse.setBeanClass(resolvedClass);
    15         }
    16 
    17         // Prepare method overrides.
    18         try {
    19             //这里是对overrides属性和look-up属性的处理
    20             mbdToUse.prepareMethodOverrides();
    21         }
    22         catch (BeanDefinitionValidationException ex) {
    23             throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
    24                     beanName, "Validation of method overrides failed", ex);
    25         }
    26 
    27         try {
    28             //AOP就是这里操作的,如果配置了postProcessor,则生成一个proxy返回,即代理类
    29             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
    30             Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
    31             if (bean != null) {
    32                 return bean;
    33             }
    34         }
    35         catch (Throwable ex) {
    36             throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
    37                     "BeanPostProcessor before instantiation of bean failed", ex);
    38         }
    39         //创建bean的方法调用
    40         Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    41         if (logger.isDebugEnabled()) {
    42             logger.debug("Finished creating instance of bean '" + beanName + "'");
    43         }
    44         return beanInstance;
    45     }

      进入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         //这里是对单例的循环引用的处理
     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会将该bean的名字存一份到singletonsCurrentlyInCreation这个map中,然后每次创建的时候都会到里面进行检查当前bean是否正在被创建。为了避免发生循环引用(A依赖B,B依赖C,C依赖A)引起是循环,在第一次创建bean时,IOC容器会把用于创建这个bean的工厂对象放入singletonFactories这个map中,key是这个正在被创建的bean的名字。这样发生循环依赖的时候,就不再调用getBean方法了,而是直接使用工厂创建一个bean给被依赖的对象。比如第一次创建A时,将A的名称存入了singletonsCurrentlyInCreation这个map中,并且调用addSingletonFactory方法,将创建A的工厂放到singletonFactories中了,然后递归调用getBean创建依赖对象B、C,创建C时,要先创建它的依赖对象A,此时,IOC容器检查到singletonsCurrentlyInCreation中已经有这个A了,说明它已经在创建的过程中,只是还没有完成创建,此时,IOC容器直接就使用这个工厂将A创建出来赋给C了,然后再往回完成B和A的创建。可以看一下addSingletonFactory方法的实现:

     1 protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
     2         Assert.notNull(singletonFactory, "Singleton factory must not be null");
     3         synchronized (this.singletonObjects) {
     4             if (!this.singletonObjects.containsKey(beanName)) {
     5                 this.singletonFactories.put(beanName, singletonFactory);
     6                 this.earlySingletonObjects.remove(beanName);
     7                 this.registeredSingletons.add(beanName);
     8             }
     9         }
    10     }
    1 public Object getSingleton(String beanName) {
    2         return getSingleton(beanName, true);
    3     }
     1 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
     2         //从缓存中获取该bean的实例,已经填充了属性值的实例
     3         Object singletonObject = this.singletonObjects.get(beanName);
     4         //创建bean时,IOC会在this.singletonsCurrentlyInCreation中存一个该bean的名称,表示正在创建这个bean
     5         if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
     6             synchronized (this.singletonObjects) {
     7                 //也是从缓存中获取实例,但是这个缓存中的实例是没有经过填充的实例
     8                 singletonObject = this.earlySingletonObjects.get(beanName);
     9                 if (singletonObject == null && allowEarlyReference) {
    10                     //获取生成该bean的beanFactory
    11                     ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    12                     if (singletonFactory != null) {
    13                         //获取这个bean的实例
    14                         singletonObject = singletonFactory.getObject();
    15                         //将这个还未经填充属性的bean存入新生代缓存中(自己取的名字,类似于JVM)
    16                         this.earlySingletonObjects.put(beanName, singletonObject);
    17                         //将这个生产bean的工厂移除
    18                         this.singletonFactories.remove(beanName);
    19                     }
    20                 }
    21             }
    22         }
    23         return (singletonObject != NULL_OBJECT ? singletonObject : null);
    24     }

      在进行递归调用getBean方法创建依赖对象之前,getSignal方法是先调用的,前面的代码,doGetBean方法中可以看到,可以多看几遍就能理解。另外,对于原型实例,不允许循环引用。循环引用只针对单例。下一篇跟踪bean的属性的填充。

  • 相关阅读:
    redis 高级
    redis连接
    redis脚本
    Redis事务
    redis发布订阅
    加一
    C语言从代码中加载动态链接库
    GCC编译器
    Vim编辑器基础
    Linux用户的创建与授权及修改密码
  • 原文地址:https://www.cnblogs.com/helei123/p/11087463.html
Copyright © 2011-2022 走看看