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

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>&lt;beans&gt;</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 时序图

解析和登记 Bean 对象时序图

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

 

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/davidwang456/article/details/9714589
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞