spring启动过程之源码跟踪(上)--spring Debug

 2019-11-02 21:22  阅读(1014)
文章分类:Spring boot

1,初始化容器

1 ClassPathXmlApplicationContext context=new
    2                 ClassPathXmlApplicationContext("/applicationContext.xml");

步骤1:构造方法如下:

1 public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
    2             throws BeansException {
    3         super(parent);
    4         setConfigLocations(configLocations);
    5         if (refresh) {
    6             refresh();
    7         }
    8     }

 步骤2:重头戏到了!

1     public void refresh() throws BeansException, IllegalStateException {
     2         synchronized (this.startupShutdownMonitor) {
     3             // Prepare this context for refreshing.
     4             prepareRefresh();
     5 
     6             // Tell the subclass to refresh the internal bean factory.
     7             ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
     8 
     9             // Prepare the bean factory for use in this context.
    10             prepareBeanFactory(beanFactory);
    11 
    12             try {
    13                 // Allows post-processing of the bean factory in context subclasses.
    14                 postProcessBeanFactory(beanFactory);
    15 
    16                 // Invoke factory processors registered as beans in the context.
    17                 invokeBeanFactoryPostProcessors(beanFactory);
    18 
    19                 // Register bean processors that intercept bean creation.
    20                 registerBeanPostProcessors(beanFactory);
    21 
    22                 // Initialize message source for this context.
    23                 initMessageSource();
    24 
    25                 // Initialize event multicaster for this context.
    26                 initApplicationEventMulticaster();
    27 
    28                 // Initialize other special beans in specific context subclasses.
    29                 onRefresh();
    30 
    31                 // Check for listener beans and register them.
    32                 registerListeners();
    33 
    34                 // Instantiate all remaining (non-lazy-init) singletons.
    35                 finishBeanFactoryInitialization(beanFactory);
    36 
    37                 // Last step: publish corresponding event.
    38                 finishRefresh();
    39             }
    40 
    41             catch (BeansException ex) {
    42                 // Destroy already created singletons to avoid dangling resources.
    43                 beanFactory.destroySingletons();
    44 
    45                 // Reset 'active' flag.
    46                 cancelRefresh(ex);
    47 
    48                 // Propagate exception to caller.
    49                 throw ex;
    50             }
    51         }
    52     }

步骤3:获取beanFactory

1     protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
     2         refreshBeanFactory();
     3         ConfigurableListableBeanFactory beanFactory = getBeanFactory();
     4 
     5         if (logger.isInfoEnabled()) {
     6             logger.info("Bean factory for application context [" + getId() + "]: " +
     7                     ObjectUtils.identityToString(beanFactory));
     8         }
     9         if (logger.isDebugEnabled()) {
    10             logger.debug(beanFactory.getBeanDefinitionCount() + " beans defined in " + this);
    11         }
    12 
    13         return beanFactory;
    14     }

步骤3-1

1     protected final void refreshBeanFactory() throws BeansException {
     2         if (hasBeanFactory()) {
     3             destroyBeans();
     4             closeBeanFactory();
     5         }
     6         try {
     7             DefaultListableBeanFactory beanFactory = createBeanFactory();
     8             customizeBeanFactory(beanFactory);
     9             loadBeanDefinitions(beanFactory);
    10             synchronized (this.beanFactoryMonitor) {
    11                 this.beanFactory = beanFactory;
    12             }
    13         }
    14         catch (IOException ex) {
    15             throw new ApplicationContextException(
    16                     "I/O error parsing XML document for application context [" + getDisplayName() + "]", ex);
    17         }
    18     }

步骤3-2 加载beans的定义(AbstractXmlApplicationContext.java)

1     /**
     2      * Loads the bean definitions via an XmlBeanDefinitionReader.
     3      * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
     4      * @see #initBeanDefinitionReader
     5      * @see #loadBeanDefinitions
     6      */
     7     protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
     8         // Create a new XmlBeanDefinitionReader for the given BeanFactory.
     9         XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    10 
    11         // Configure the bean definition reader with this context's
    12         // resource loading environment.
    13         beanDefinitionReader.setResourceLoader(this);
    14         beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
    15 
    16         // Allow a subclass to provide custom initialization of the reader,
    17         // then proceed with actually loading the bean definitions.
    18         initBeanDefinitionReader(beanDefinitionReader);
    19         loadBeanDefinitions(beanDefinitionReader);
    20     }

步骤3-3

1 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
     2         Resource[] configResources = getConfigResources();
     3         if (configResources != null) {
     4             reader.loadBeanDefinitions(configResources);
     5         }
     6         String[] configLocations = getConfigLocations();
     7         if (configLocations != null) {
     8  reader.loadBeanDefinitions(configLocations);
     9         }
    10     }

步骤3-4 XmlBeanDefinitionReader.java

1     public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
     2         Assert.notNull(encodedResource, "EncodedResource must not be null");
     3         if (logger.isInfoEnabled()) {
     4             logger.info("Loading XML bean definitions from " + encodedResource.getResource());
     5         }
     6 
     7         Set currentResources = (Set) this.resourcesCurrentlyBeingLoaded.get();
     8         if (currentResources == null) {
     9             currentResources = new HashSet(4);
    10             this.resourcesCurrentlyBeingLoaded.set(currentResources);
    11         }
    12         if (!currentResources.add(encodedResource)) {
    13             throw new BeanDefinitionStoreException(
    14                     "Detected recursive loading of " + encodedResource + " - check your import definitions!");
    15         }
    16         try {
    17             InputStream inputStream = encodedResource.getResource().getInputStream();
    18             try {
    19                 InputSource inputSource = new InputSource(inputStream);
    20                 if (encodedResource.getEncoding() != null) {
    21                     inputSource.setEncoding(encodedResource.getEncoding());
    22                 }
    23                 return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    24             }
    25             finally {
    26                 inputStream.close();
    27             }
    28         }
    29         catch (IOException ex) {
    30             throw new BeanDefinitionStoreException(
    31                     "IOException parsing XML document from " + encodedResource.getResource(), ex);
    32         }
    33         finally {
    34             currentResources.remove(encodedResource);
    35             if (currentResources.isEmpty()) {
    36                 this.resourcesCurrentlyBeingLoaded.set(null);
    37             }
    38         }
    39     }

步骤3-5 读取xml文件
DefaultBeanDefinitionDocumentReader.java

1     /**
     2      * Parses bean definitions according to the "spring-beans" DTD.
     3      * <p>Opens a DOM Document; then initializes the default settings
     4      * specified at <code><beans></code> level; then parses
     5      * the contained bean definitions.
     6      */
     7     public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
     8         this.readerContext = readerContext;
     9 
    10         logger.debug("Loading bean definitions");
    11         Element root = doc.getDocumentElement();
    12 
    13         BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
    14 
    15         preProcessXml(root);
    16         parseBeanDefinitions(root, delegate);
    17         postProcessXml(root);
    18     }

(以下图片为网上所得,非原创,谢谢原作者)

创建 BeanFactory 时序图

![Image 1][]

解析和登记 Bean 对象时序图

![Image 1][]

20191102100758\_1.png

[Image 1]:


来源:http://ddrv.cn

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> spring启动过程之源码跟踪(上)--spring Debug

相关推荐