ClassPathXmlApplicationContext类体系结构

以下是ClassPathXmlApplicationContext的类继承体系结构,理解这个结构有助于后面的代码理解。



d9a0e8c8-29d6-36a3-888e-e22c2d1bb44f.jpg


左边×××部分是ApplicationContext体系继承结构,右边是BeanFactory的结构体系,两个结构是典型模板方法设计模式的使用。

从该继承体系可以看出:

1.BeanFactory是一个bean工厂的最基本定义,里面包含了一个bean工厂的几个最基本的方法,getBean(…)、containsBean(…)等,是一个很纯粹的bean工厂,不关注资源、资源位置、事件等。ApplicationContext是一个容器的最基本接口定义,它继承了BeanFactory,拥有工厂的基本方法。同时继承了ApplicationEventPublisherMessageSourceResourcePatternResolver等接口,使其定义了一些额外的功能,如资源、事件等这些额外的功能。

2.AbstractBeanFactoryAbstractAutowireCapableBeanFactory是两个模板抽象工厂类。AbstractBeanFactory提供了bean工厂的抽象基类,同时提供了ConfigurableBeanFactory的完整实现。AbstractAutowireCapableBeanFactory是继承了AbstractBeanFactory的抽象工厂,里面提供了bean创建的支持,包括bean的创建、依赖注入、检查等等功能,是一个核心的bean工厂基类。

3.ClassPathXmlApplicationContext之所以拥有bean工厂的功能是通过持有一个真正的bean工厂DefaultListableBeanFactory的实例,并通过代理该工厂完成。

4.ClassPathXmlApplicationContext的初始化过程是对本身容器的初始化同时也是对其持有的DefaultListableBeanFactory的初始化。


下面通过源码着重介绍一个容器的初始化过程,并重点理解bean的创建过程。



容器初始化过程

通过上文啃啃老菜: Spring IOC核心源码学习(一)已经可以了解一个容器的大概过程是:



370101b5-b3d1-3b79-b9b2-3bba91d092d7.jpg



整个过程可以理解为是容器的初始化过程。第一个过程是ApplicationContext的职责范围,第二步是BeanFactory的职责范围。可以看出ApplicationContext是一个运行时的容器需要提供不容资源环境的支持,屏蔽不同环境的差异化。而BeanDifinition是内部关于bean定义的基本结构。Bean的创建就是基于它,回头会介绍一下改结构的定义。下面看一下整个容器的初始化过程。


容器的初始化是通过调用refresh()来实现。该方法是非常重要的一个方法,定义在AbstractApplicationContext接口里。AbstractApplicationContext是容器的最基础的一个抽象父类。也就是说在该里面定义了一个容器初始化的基本流程,流程里的各个方法有些有提供了具体实现,有些是抽象的(因为不同的容器实例不一样),由继承它的每一个具体容器完成定制。看看refresh的基本流程:

Java代码   收藏代码
  1. publicvoid refresh() throws BeansException, IllegalStateException {  

  2. synchronized (this.startupShutdownMonitor) {  

  3. // Prepare this context for refreshing.

  4.            prepareRefresh();  

  5. // Tell the subclass to refresh the internal bean factory.

  6.            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  

  7. // Prepare the bean factory for use in this context.

  8.            prepareBeanFactory(beanFactory);  

  9. try {  

  10. // Allows post-processing of the bean factory in context subclasses.

  11.                postProcessBeanFactory(beanFactory);  

  12. // Invoke factory processors registered as beans in the context.

  13.                invokeBeanFactoryPostProcessors(beanFactory);  

  14. // Register bean processors that intercept bean creation.

  15.                registerBeanPostProcessors(beanFactory);  

  16. // Initialize message source for this context.

  17.                initMessageSource();  

  18. // Initialize event multicaster for this context.

  19.                initApplicationEventMulticaster();  

  20. // Initialize other special beans in specific context subclasses.

  21.                onRefresh();  

  22. // Check for listener beans and register them.

  23.                registerListeners();  

  24. // Instantiate all remaining (non-lazy-init) singletons.

  25.                finishBeanFactoryInitialization(beanFactory);  

  26. // Last step: publish corresponding event.

  27.                finishRefresh();  

  28.            }  

  29. catch (BeansException ex) {  

  30. // Destroy already created singletons to avoid dangling resources.

  31.                beanFactory.destroySingletons();  

  32. // Reset 'active' flag.

  33.                cancelRefresh(ex);  

  34. // Propagate exception to caller.

  35. throw ex;  

  36.            }  

  37.        }  

  38.    }  

解释如下:



2187e288-5c0b-313b-8053-82992267fab6.jpg



Bean的创建过程

Bean的创建过程基本是BeanFactory所要完成的事情.

根据以上过程,将会重点带着以下两个个问题来理解核心代码:

1.Bean的创建时机

bean是在什么时候被创建的,有哪些规则。

2.Bean的创建过程

bean是怎么创建的,会选择哪个构造函数?依赖如何注入?InitializingBeanset方法什么时候被调用?实现ApplicationContextAware, BeanFactoryAware,BeanNameAware,ResourceLoaderAware 这些接口的beanset方法何时被调用?


在解释这两个问题前,先看一下BeanDefinition接口的定义。


2beb44aa-4b38-3d87-a444-308d8f380e87.jpg


从该接口定义可以看出,通过bean定义能够得到bean的详细信息,如类名子、工厂类名称、scope、是否单例、是否抽象、是否延迟加载等等。基于此,来看一下以下两个问题:





问题1:Bean的创建时机

bean是在什么时候被创建的,有哪些规则?

容器初始化的时候会预先对单例和非延迟加载的对象进行预先初始化。其他的都是延迟加载是在第一次调用getBean的时候被创建。从DefaultListableBeanFactory的preInstantiateSingletons里可以看到这个规则的实现。

Java代码   收藏代码
  1. publicvoid preInstantiateSingletons() throws BeansException {  

  2. if (this.logger.isInfoEnabled()) {  

  3. this.logger.info("Pre-instantiating singletons in " + this);  

  4.        }  


  5. synchronized (this.beanDefinitionMap) {  

  6. for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {  

  7.                String beanName = (String) it.next();  

  8.                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);  

  9.                <span style="color: #ff0000;">if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {</span>  




  10. //对非抽象、单例的和非延迟加载的对象进行实例化。

  11. if (isFactoryBean(beanName)) {  

  12.                        FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);  

  13. if (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()) {  

  14.                            getBean(beanName);  

  15.                        }  

  16.                    }  

  17. else {  

  18.                        getBean(beanName);  

  19.                    }  

  20.                }  

  21.            }  

  22.        }  

  23.    }  


从上面来看对于以下配置,只有singletonBean会被预先创建。

Xml代码   收藏代码
  1. <?xmlversion="1.0"encoding="GB2312"?>

  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

  3. <beansdefault-autowire="byName">

  4. <beanid="otherBean"class="com.test.OtherBean"scope="prototype"/>

  5. <beanid="myBean"class="com.test.MyBean"lazy-init="true"/>

  6. <beanid="singletonBean"class="com.test.SingletonBean"/>

  7. </beans>




问题二:Bean的创建过程

对于bean的创建过程其实都是通过调用工厂的getBean方法来完成的。这里面将会完成对构造函数的选择、依赖注入等。


无论预先创建还是延迟加载都是调用getBean实现,AbstractBeanFactory定义了getBean的过程:

Java代码   收藏代码
  1. protected Object doGetBean(  

  2. final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {  

  3. final String beanName = transformedBeanName(name);  

  4.        Object bean = null;  

  5. // Eagerly check singleton cache for manually registered singletons.

  6.        Object sharedInstance = getSingleton(beanName);  

  7. if (sharedInstance != null && args == null) {  

  8. if (logger.isDebugEnabled()) {  

  9. if (isSingletonCurrentlyInCreation(beanName)) {  

  10.                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +  

  11. "' that is not fully initialized yet - a consequence of a circular reference");  

  12.                }  

  13. else {  

  14.                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");  

  15.                }  

  16.            }  

  17.            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  

  18.        }  

  19. else {  

  20. // Fail if we're already creating this bean instance:

  21. // We're assumably within a circular reference.

  22. if (isPrototypeCurrentlyInCreation(beanName)) {  

  23. thrownew BeanCurrentlyInCreationException(beanName);  

  24.            }  


  25. // Check if bean definition exists in this factory.

  26.            BeanFactory parentBeanFactory = getParentBeanFactory();  

  27. if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  

  28. // Not found -> check parent.

  29.                String nameToLookup = originalBeanName(name);  

  30. if (args != null) {  

  31. // Delegation to parent with explicit args.

  32. return parentBeanFactory.getBean(nameToLookup, args);  

  33.                }  

  34. else {  

  35. // No args -> delegate to standard getBean method.

  36. return parentBeanFactory.getBean(nameToLookup, requiredType);  

  37.                }  

  38.            }  


  39. if (!typeCheckOnly) {  

  40.                markBeanAsCreated(beanName);  

  41.            }  


  42. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  

  43.            checkMergedBeanDefinition(mbd, beanName, args);  


  44. // Guarantee initialization of beans that the current bean depends on.

  45.            String[] dependsOn = mbd.getDependsOn();  

  46. if (dependsOn != null) {  

  47. for (int i = 0; i < dependsOn.length; i++) {  

  48.                    String dependsOnBean = dependsOn[i];  

  49.                    getBean(dependsOnBean);  

  50.                    registerDependentBean(dependsOnBean, beanName);  

  51.                }  

  52.            }  

  53. // Create bean instance.

  54.            <span style="color: #ff0000;">if (mbd.isSingleton()) {//单例对象创建过程,间接通过getSingleton方法来创建,里面会实现将单例对象缓存</span>





  55.                sharedInstance = getSingleton(beanName, new ObjectFactory() {  

  56. public Object getObject() throws BeansException {  

  57. try {  

  58. return createBean(beanName, mbd, args);  

  59.                        }  

  60. catch (BeansException ex) {  

  61. // Explicitly remove instance from singleton cache: It might have been put there

  62. // eagerly by the creation process, to allow for circular reference resolution.

  63. // Also remove any beans that received a temporary reference to the bean.

  64.                            destroySingleton(beanName);  

  65. throw ex;  

  66.                        }  

  67.                    }  

  68.                });  

  69.                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  

  70.            }  


  71.            <span style="color: #ff0000;">elseif (mbd.isPrototype()) {//非单例对象创建</span>





  72. // It's a prototype -> create a new instance.

  73.                Object prototypeInstance = null;  

  74. try {  

  75.                    beforePrototypeCreation(beanName);  

  76.                    prototypeInstance = createBean(beanName, mbd, args);<span style="color: #ff0000;">//直接调用createBean</span>





  77.                }  

  78. finally {  

  79.                    afterPrototypeCreation(beanName);  

  80.                }  

  81.                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  

  82.            }  


  83. else {  

  84.                String scopeName = mbd.getScope();  

  85. final Scope scope = (Scope) this.scopes.get(scopeName);  

  86. if (scope == null) {  

  87. thrownew IllegalStateException("No Scope registered for scope '" + scopeName + "'");  

  88.                }  

  89. try {  

  90.                    Object scopedInstance = scope.get(beanName, new ObjectFactory() {  

  91. public Object getObject() throws BeansException {  

  92.                            beforePrototypeCreation(beanName);  

  93. try {  

  94. return createBean(beanName, mbd, args);  

  95.                            }  

  96. finally {  

  97.                                afterPrototypeCreation(beanName);  

  98.                            }  

  99.                        }  

  100.                    });  

  101.                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);  

  102.                }  

  103. catch (IllegalStateException ex) {  

  104. thrownew BeanCreationException(beanName,  

  105. "Scope '" + scopeName + "' is not active for the current thread; " +  

  106. "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",  

  107.                            ex);  

  108.                }  

  109.            }  

  110.        }  

  111. // Check if required type matches the type of the actual bean instance.

  112. if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {  

  113. thrownew BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());  

  114.        }  

  115. return bean;  

  116.    }  





GetBean的大概过程:

1.先试着从单例缓存对象里获取。

2.从父容器里取定义,有则由父容器创建。

3.如果是单例,则走单例对象的创建过程:在spring容器里单例对象和非单例对象的创建过程是一样的。都会调用父类AbstractAutowireCapableBeanFactorycreateBean方法。不同的是单例对象只创建一次并且需要缓存起来。DefaultListableBeanFactory的父类DefaultSingletonBeanRegistry提供了对单例对象缓存等支持工作。所以是单例对象的话会调用DefaultSingletonBeanRegistrygetSingleton方法,它会间接调用AbstractAutowireCapableBeanFactorycreateBean方法。

如果是Prototype多例则直接调用父类AbstractAutowireCapableBeanFactorycreateBean方法。


bean的创建是由AbstractAutowireCapableBeanFactory来定义:


Java代码   收藏代码
  1. protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)  

  2. throws BeanCreationException {  

  3.        AccessControlContext acc = AccessController.getContext();  

  4. return AccessController.doPrivileged(new PrivilegedAction() {  

  5. public Object run() {  

  6. if (logger.isDebugEnabled()) {  

  7.                    logger.debug("Creating instance of bean '" + beanName + "'");  

  8.                }  

  9. // Make sure bean class is actually resolved at this point.

  10.                resolveBeanClass(mbd, beanName);  

  11. // Prepare method overrides.

  12. try {  

  13.                    mbd.prepareMethodOverrides();  

  14.                }  

  15. catch (BeanDefinitionValidationException ex) {  

  16. thrownew BeanDefinitionStoreException(mbd.getResourceDescription(),  

  17.                            beanName, "Validation of method overrides failed", ex);  

  18.                }  

  19. try {  

  20. // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

  21.                    Object bean = resolveBeforeInstantiation(beanName, mbd);  

  22. if (bean != null) {  

  23. return bean;  

  24.                    }  

  25.                }  

  26. catch (Throwable ex) {  

  27. thrownew BeanCreationException(mbd.getResourceDescription(), beanName,  

  28. "BeanPostProcessor before instantiation of bean failed", ex);  

  29.                }  

  30.                Object beanInstance = doCreateBean(beanName, mbd, args);  

  31. if (logger.isDebugEnabled()) {  

  32.                    logger.debug("Finished creating instance of bean '" + beanName + "'");  

  33.                }  

  34. return beanInstance;  

  35.            }  

  36.        }, acc);  

  37.    }  

createBean会调用doCreateBean方法:


Java代码   收藏代码
  1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {  

  2. // Instantiate the bean.

  3.        BeanWrapper instanceWrapper = null;  

  4. if (mbd.isSingleton()) {  

  5.            instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);  

  6.        }  

  7. if (instanceWrapper == null) {  

  8.            instanceWrapper = createBeanInstance(beanName, mbd, args);  

  9.        }  

  10. final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);  

  11.        Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);  


  12. // Allow post-processors to modify the merged bean definition.

  13. synchronized (mbd.postProcessingLock) {  

  14. if (!mbd.postProcessed) {  

  15.                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);  

  16.                mbd.postProcessed = true;  

  17.            }  

  18.        }  


  19. // Eagerly cache singletons to be able to resolve circular references

  20. // even when triggered by lifecycle interfaces like BeanFactoryAware.

  21. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&  

  22.                isSingletonCurrentlyInCreation(beanName));  

  23. if (earlySingletonExposure) {  

  24. if (logger.isDebugEnabled()) {  

  25.                logger.debug("Eagerly caching bean '" + beanName +  

  26. "' to allow for resolving potential circular references");  

  27.            }  

  28.            addSingletonFactory(beanName, new ObjectFactory() {  

  29. public Object getObject() throws BeansException {  

  30. return getEarlyBeanReference(beanName, mbd, bean);  

  31.                }  

  32.            });  

  33.        }  

  34. // Initialize the bean instance.

  35.        Object exposedObject = bean;  

  36. try {  

  37.            populateBean(beanName, mbd, instanceWrapper);  

  38.            exposedObject = initializeBean(beanName, exposedObject, mbd);  

  39.        }  

  40. catch (Throwable ex) {  

  41. if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {  

  42. throw (BeanCreationException) ex;  

  43.            }  

  44. else {  

  45. thrownew BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);  

  46.            }  

  47.        }  

  48. if (earlySingletonExposure) {  

  49.            Object earlySingletonReference = getSingleton(beanName, false);  

  50. if (earlySingletonReference != null) {  

  51. if (exposedObject == bean) {  

  52.                    exposedObject = earlySingletonReference;  

  53.                }  

  54. elseif (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {  

  55.                    String[] dependentBeans = getDependentBeans(beanName);  

  56.                    Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);  

  57. for (int i = 0; i < dependentBeans.length; i++) {  

  58.                        String dependentBean = dependentBeans[i];  

  59. if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {                         actualDependentBeans.add(dependentBean);  

  60.                        }  

  61.                    }  

  62. if (!actualDependentBeans.isEmpty()) {  

  63. thrownew BeanCurrentlyInCreationException(beanName,  

  64. "Bean with name '" + beanName + "' has been injected into other beans [" +  

  65.                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  

  66. "] in its raw version as part of a circular reference, but has eventually been " +  

  67. "wrapped. This means that said other beans do not use the final version of the " +  

  68. "bean. This is often the result of over-eager type matching - consider using " +  

  69. "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");  

  70.                    }  

  71.                }  

  72.            }  

  73.        }  

  74. // Register bean as disposable.

  75.        registerDisposableBeanIfNecessary(beanName, bean, mbd);  

  76. return exposedObject;  

  77.    }  


doCreateBean的流程:

1.会创建一个BeanWrapper 对象用于存放实例化对象。

2.如果没有指定构造函数,会通过反射拿到一个默认的构造函数对象,并赋予beanDefinition.resolvedConstructorOrFactoryMethod。

3.调用spring的BeanUtils的instantiateClass方法,通过反射创建对象。

4.applyMergedBeanDefinitionPostProcessors

5.populateBean(beanName,mbd, instanceWrapper);根据注入方式进行注入。根据是否有依赖检查进行依赖检查。

执行bean的注入里面会选择注入类型:

Java代码   收藏代码
  1. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||  

  2.                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  

  3.            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  


  4. // Add property values based on autowire by name if applicable.

  5. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {  

  6.                autowireByName(beanName, mbd, bw, newPvs);  

  7.            }<span style="color: #ff0000;">//根据名字注入</span>






  8. // Add property values based on autowire by type if applicable.

  9. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  

  10.                autowireByType(beanName, mbd, bw, newPvs);  

  11.            }<span style="color: #ff0000;">//根据类型注入</span>






  12.            pvs = newPvs;  

  13.        }  

6.initializeBean(beanName, exposedObject, mbd);

判断是否实现了BeanNameAwareBeanClassLoaderAwarespring提供的接口,如果实现了,进行默认的注入。同时判断是否实现了InitializingBean接口,如果是的话,调用afterPropertySet方法。


Java代码   收藏代码
  1. protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {  

  2. if (bean instanceof BeanNameAware) {  

  3.            ((BeanNameAware) bean).setBeanName(beanName);  

  4.        }  

  5. if (bean instanceof BeanClassLoaderAware) {  

  6.            ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());  

  7.        }  

  8. if (bean instanceof BeanFactoryAware) {  

  9.            ((BeanFactoryAware) bean).setBeanFactory(this);  

  10.        }  

  11.        Object wrappedBean = bean;  

  12. if (mbd == null || !mbd.isSynthetic()) {  

  13.            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  

  14.        }  

  15. <span style="color: #ff0000;">      try {  

  16.            invokeInitMethods(beanName, wrappedBean, mbd);  

  17.        }</span>  





  18. catch (Throwable ex) {  

  19. thrownew BeanCreationException(  

  20.                    (mbd != null ? mbd.getResourceDescription() : null),  

  21.                    beanName, "Invocation of init method failed", ex);  

  22.        }  


  23. if (mbd == null || !mbd.isSynthetic()) {  

  24.            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  

  25.        }  

  26. return wrappedBean;  

  27.    }  

其中invokeInitMethods实现如下:

Java代码   收藏代码
  1. protectedvoid invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)  

  2. throws Throwable {  


  3. boolean isInitializingBean = (bean instanceof InitializingBean);  

  4. if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {  

  5. if (logger.isDebugEnabled()) {  

  6.            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");  

  7.        }  

  8.        ((InitializingBean) bean).afterPropertiesSet();<span style="color: #ff0000;">//调用afterPropertiesSet方法</span>





  9.    }  


  10.    String initMethodName = (mbd != null ? mbd.getInitMethodName() : null);  

  11. if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&  

  12.            !mbd.isExternallyManagedInitMethod(initMethodName)) {  

  13.        invokeCustomInitMethod(beanName, bean, initMethodName, mbd.isEnforceInitMethod());  

  14.    }  

  15. }  



总结

以上基本描述了spring容器的初始化过程和bean的创建过程。主要还是从大处着眼,很多细节没有涉及到。代码阅读总体感觉就是spring的代码抽象很好,结合结构读起来还是蛮顺利的。后面的学习将从细节着手。