spring源码解析之IOC容器(三)——依赖注入

2019-06-26

  上一篇主要是跟踪了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的属性的填充。