1. 程式人生 > >spring bean 載入過程(spring)

spring bean 載入過程(spring)

 

以classpathXmlApplication為例

入口方法包含3個部分,

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {
        super(parent);
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
    }

1.繼承父類,沒什麼東西

2.設定配置檔案

3.執行refresh方法(關鍵)。下面我們就這兩個方法看看內部實現

 

設定配置檔案,這塊其實沒什麼東西,就是給context物件設定一個configLocations的陣列,我們看一下context類的繼承關係

 

下面看重點的refresh方法

 1 public void refresh() throws BeansException, IllegalStateException {
 2         synchronized (this.startupShutdownMonitor) {//鎖住一個物件,防止多執行緒同時執行初始化的操作
3 // Prepare this context for refreshing.準備上下文,這裡設定一下開始實現,準備propery等 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 if (logger.isWarnEnabled()) { 43 logger.warn("Exception encountered during context initialization - " + 44 "cancelling refresh attempt: " + ex); 45 } 46 47 // Destroy already created singletons to avoid dangling resources. 48 destroyBeans(); 49 50 // Reset 'active' flag. 51 cancelRefresh(ex); 52 53 // Propagate exception to caller. 54 throw ex; 55 } 56 57 finally { 58 // Reset common introspection caches in Spring's core, since we 59 // might not ever need metadata for singleton beans anymore... 60 resetCommonCaches(); 61 } 62 } 63 }

這個程式碼有點長,我們把每個方法幹什麼先研究一下,在深入看每個方法怎麼實現的。

從7行開始看,這個方法是為了一個refreshBeanFactory。返回的類是ConfigurableListableBeanFactory,而這個factory是一個介面,我們待會看看這個介面有哪些實現,先看看這個方法內部實現

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

我們看到最後return的beanFactory就是ConfigurableListableBeanFactory。而這個介面只有一個default實現類DefaultListableBeanFactory。我們看看這個類主要有哪些成員變數

 1 private boolean allowEagerClassLoading = true;
 2 
 3     /** Optional OrderComparator for dependency Lists and arrays */
 4     private Comparator<Object> dependencyComparator;
 5 
 6     /** Resolver to use for checking if a bean definition is an autowire candidate */
 7     private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
 8 
 9     /** Map from dependency type to corresponding autowired value */
10     private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<Class<?>, Object>(16);
11 
12     /** Map of bean definition objects, keyed by bean name */
13     private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(256);
14 
15     /** Map of singleton and non-singleton bean names, keyed by dependency type */
16     private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
17 
18     /** Map of singleton-only bean names, keyed by dependency type */
19     private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
20 
21     /** List of bean definition names, in registration order */
22     private volatile List<String> beanDefinitionNames = new ArrayList<String>(256);
23 
24     /** List of names of manually registered singletons, in registration order */
25     private volatile Set<String> manualSingletonNames = new LinkedHashSet<String>(16);
26 
27     /** Cached array of bean definition names in case of frozen configuration */
28     private volatile String[] frozenBeanDefinitionNames;
29 
30     /** Whether bean definition metadata may be cached for all beans */
31     private volatile boolean configurationFrozen = false;

這些成員變數有機會我們一個個分析下,我們知道每個bean 有一個beanDefinition物件來定義。在13行,我們看到有一個BeanDefinition的Map,我們隨便除錯一下,看看這個裡面存了什麼東西。

這裡面竟然只有7個物件,分別是:ConfigurationClassPostProcessor、DefaultEventListenerFactory、MessageResolver、EventListenerMethodProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PropertiesFactoryBean、RequiredAnnotationBeanPostProcessor。這七個物件怎麼來的呢,舉個例子來看ConfigurationClassPostProcessor,這個類說明是,當配置檔案中

Registered by default when using {@code <context:annotation-config/>} or
* {@code <context:component-scan/>}有這兩個配置的時候,便會注入這麼個類。好吧,那我們看看在哪裡register的。我們猜測是在

refreshBeanFactory();這個方法裡面。那看看這個方法
 1 protected final void refreshBeanFactory() throws BeansException {
 2         if (hasBeanFactory()) {
 3             destroyBeans();
 4             closeBeanFactory();
 5         }
 6         try {
 7             DefaultListableBeanFactory beanFactory = createBeanFactory();
 8             beanFactory.setSerializationId(getId());
 9             customizeBeanFactory(beanFactory);
10             loadBeanDefinitions(beanFactory);
11             synchronized (this.beanFactoryMonitor) {
12                 this.beanFactory = beanFactory;
13             }
14         }
15         catch (IOException ex) {
16             throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
17         }
18     }

我們看到第7行,建立了一個DefaultListableBeanFactory ,第10行有loadBeanDefinition。應該是在這裡處理的。我們還是先除錯下看看。執行7行程式碼,這個時候beanDefinitionMap是空的。執行完10行程式碼,我們的beanDefinitionMap有值了。這裡面為了加深理解,我們在我們的spring-config.xml檔案中加一個bean看看會怎麼樣。原來的spring-config.xml檔案如下

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:context="http://www.springframework.org/schema/context"
 5        xmlns:util="http://www.springframework.org/schema/util"
 6        xsi:schemaLocation="
 7            http://www.springframework.org/schema/beans
 8            http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
 9            http://www.springframework.org/schema/context
10            http://www.springframework.org/schema/context/spring-context-4.1.xsd
11            http://www.springframework.org/schema/util
12            http://www.springframework.org/schema/util/spring-util-4.1.xsd">
13 
14     <context:annotation-config/>
15     
16     <context:component-scan base-package="com.newbie.common"></context:component-scan>
17 
18     <util:properties id="systemProperties" location="classpath:conf/user.properties" />
19     
20     
21 </beans>

我們隨便加一個bean,如下圖所示,有多個一個beanDefinition。所以這個地就是定義所以beanDefinition的入口,而我們從autowire的bean是由相關processor處理的,這個今後如果有時間的話,我們在分析。我們繼續往下看

我們回到原來的refresh方法裡面。

 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                 if (logger.isWarnEnabled()) {
43                     logger.warn("Exception encountered during context initialization - " +
44                             "cancelling refresh attempt: " + ex);
45                 }
46 
47                 // Destroy already created singletons to avoid dangling resources.
48                 destroyBeans();
49 
50                 // Reset 'active' flag.
51                 cancelRefresh(ex);
52 
53                 // Propagate exception to caller.
54                 throw ex;
55             }
56 
57             finally {
58                 // Reset common introspection caches in Spring's core, since we
59                 // might not ever need metadata for singleton beans anymore...
60                 resetCommonCaches();
61             }
62         }
63     }

我們現在知道第7行返回的這個ConfigurableListableBeanFactory 有我們所有的beanDefintion。這個方法是給ConfigurableListableBeanFactory 設定了若干預設變數,現在我們也不清楚這個變數是幹嘛的,我們先跳過這個方法,等回頭再分析他。

第14行postProcessBeanFactory(ConfigurableListableBeanFactory )。我們看看這個程式碼是做什麼事情,我們有一個關注點,我們@autowired的bean是怎麼被處理的。這個程式碼,會根據不同context子類加入不同Processors,這個我們也暫時不分析他,等回頭再看

第17行invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory )。這個方法應該就是能看到bean是如何建立的。這個程式碼比較長,我們先把呼叫關係簡單畫出來

執行invokeBeanFactoryPostProcessors之後,這裡主要是講各個processors類註冊進去,這裡需要獲得具體的bean了,根據beanName和BeanDefinition。如何獲得bean,通過DefaultListableBeanFactory的getBean方法,這裡判斷bean是單利還是原型的,進入不同的getBean的邏輯,之後呼叫的AbstractAutowireCapableBeanFactory的createBean方法,之後通過反射來獲得對應的bean。注意看一下doCreateBean方法裡面的populateBean()方法,這裡能夠完成對屬性的注入。

上面這個方法,我們呼叫的時候發現就註冊了一個ConfigurationClassPostProcessor,也不知道幹嘛的。後來通過搜尋瞭解到這個方法主要是用於處理spring的後置處理器的相關內容,參考https://www.cnblogs.com/sishang/p/6588542.html和https://www.cnblogs.com/sishang/p/6576665.html。