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

Posted helei123

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的属性的填充。

以上是关于spring源码解析之IOC容器——依赖注入的主要内容,如果未能解决你的问题,请参考以下文章

spring源码之IOC的依赖注入

Spring源码解析

Java面试Spring源码分析 —— Spring IoC

spring依赖注入源码分析

手写Spring的IOC容器和DI依赖注入

学习spring容器IOC之依赖和依赖注入