Spring ApplicationContext 初始化流程


主題

學習記錄一下applicationContext在初始化過程中做的一些操作..

從全局整體來看.不會涉及太多細節.

 

applicationcontext的refresh方法是一個startup method.算是spring啟動的一個方法.它處理各種配置,不管是XML還是properties還是啥.創建了各種bean.算是一個最核心的方法.

refresh方法里面包含了一大堆模板方法.每個模板都做了一些事情,相當於一個小步驟..

從代碼整體來看大概包含了這么一些步驟.其中2,3,4,5,6這幾部是我個人覺得最核心的步驟.我想特別記錄下我的想法

 

1. prepareRefresh

 1     /**
 2      * Prepare this context for refreshing, setting its startup date and
 3      * active flag as well as performing any initialization of property sources.
 4      */
 5     protected void prepareRefresh() {
 6         this.startupDate = System.currentTimeMillis();
 7         this.active.set(true);
 8 
 9         if (logger.isInfoEnabled()) {
10             logger.info("Refreshing " + this);
11         }
12 
13         // Initialize any placeholder property sources in the context environment
14         initPropertySources();
15 
16         // Validate that all properties marked as required are resolvable
17         // see ConfigurablePropertyResolver#setRequiredProperties
18         getEnvironment().validateRequiredProperties();
19 
20         // Allow for the collection of early ApplicationEvents,
21         // to be published once the multicaster is available...
22         this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
23     }
View Code

這個方法基本啥都沒做.留給子類ac去做自定義的操作.

比如web環境下的ac可能會將servletConfig或者servletContext里配置的一些參數值也當做屬性值加入到spring中.因為你的spring的部分配置可能會依賴這些web.xml里的配置

另外就是對必要屬性的驗證.如果有必要的話可以自己去寫一個ac繼承spring,然后重寫initPropertySources方法去設置你覺得必要的屬性.然后當getEnvironment().validateRequiredProperties();

的時候如果沒有找到你之前setRequiredProperties的那些屬性.就會提示報錯.

 

 

2. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

獲取BF這個步驟主要作用就是構造一個bf.然后去加載對應的beanDifination信息.

    /**
     * Tell the subclass to refresh the internal bean factory.
     * @return the fresh BeanFactory instance
     * @see #refreshBeanFactory()
     * @see #getBeanFactory()
     */
    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }

getBeanFactory方法就是獲取當前這個ac里設置的bf,沒啥好說的.主要看看refreshBeanFactory這個方法里面做了啥.

 1     /**
 2      * This implementation performs an actual refresh of this context's underlying
 3      * bean factory, shutting down the previous bean factory (if any) and
 4      * initializing a fresh bean factory for the next phase of the context's lifecycle.
 5      */
 6     @Override
 7     protected final void refreshBeanFactory() throws BeansException {
 8         if (hasBeanFactory()) {
 9             destroyBeans();
10             closeBeanFactory();
11         }
12         try {
13             DefaultListableBeanFactory beanFactory = createBeanFactory();
14             beanFactory.setSerializationId(getId());
15             customizeBeanFactory(beanFactory);
16             // 這里不同的ac可能會有不同的loadDefination的方法,比如AnnotationConfigWebApplicationContext就會掃描注解注冊BD
17             loadBeanDefinitions(beanFactory);
18             synchronized (this.beanFactoryMonitor) {
19                 this.beanFactory = beanFactory;
20             }
21         }
22         catch (IOException ex) {
23             throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
24         }
25     }
View Code

 

2.1 shuwdown之前的bf

如果當前這個ac已經有bf了(比如之前ac的refresh就調用過)了.那這里需要把這個bf shutdown.

比如把bf里的各種緩存的map情況.然后所有的單例bean如果impl了DisposableBean,還需要調用它的destroy方法去做相應的操作.

 

2.2 創建bf

DefaultListableBeanFactory beanFactory = createBeanFactory();

createBeanFactory默認返回的是DefaultListableBeanFactory類的實例.目前為止spring中還沒看到其他繼承這個BF的實現類.基本都是用這個類作為默認的BF.可能因為功能已經足夠強大了吧..另外因為ApplicationContext也繼承了BF,所以很多操作會在ac里操作掉..根據ac的不同實現做不同的操作.可能這也是bf沒有這么多實現的原因吧...

 

2.3 配置bf

customizeBeanFactory(beanFactory);

這是一個模板方法.允許子類ac去實現他.對bf進行一些個性化配置.比如是否需要解決單例的循環依賴呀? 是否允許beanDifination多次定義被覆蓋呀? 

bf里配置還蠻多的..不過我看源碼里目前子類ac也沒啥進行定制的...

 

2.4 加載bd

loadBeanDefinitions(beanFactory);

BeanFactory的作用就是讀取bean的配置信息變成內存中的BeanDifination.然后在創建bean的時候根據這個bd去構造具體的bean.

不同的bean的配置方式可能各種各樣.比如有XML的.Properties的.傳統注解@Service@Autowired的.又或是@Configuration這種java config方式的..但是他們在內存中都是通過BeanDifination來表示的(可能是不同子類).

不同的ApplicationContext代表了不同的環境.比如適用於web環境的WebApplicationContext,也有傳統單獨使用spring的時候的XML里的ClassPathXmlApplicationContext等等

這些不同的ac加載bd的方式也會各有不同.所以在這個loadBeanDefinitions模板方法里就是要根據不同的ac去實現不同的加載bd的方式.

比如XML的ac就應該委托XmlBeanDefinitionReader去讀取bean形式的配置.轉化成BeanDifination注冊到BF中.

而支持Annotation的ac就應該委托AnnotatedBeanDefinitionReader這種reader去掃描Java源碼.注冊相應的BD.

 

當然.注冊的BD不一定就是我們代碼里用到的那些bean對應的bd.也可能是一些BeanPostProcessor或者子接口的實現類.

因為比如InstantiationAwareBeanPostProcessor類似這種特殊的接口都是參與Spring的生命周期可以在一些必要的時候替換掉原始的bean.或者對bean的屬性進行一些加工.

比如@Autowired這種操作就是用到特殊的bpp..AutowiredAnnotationBeanPostProcessor..同理@Configuration也是一樣..

 

所以說不同的bean的配置方式在spring創建對應的bean過程中走的流程可能是不一樣的,這也是Spring比較靈活的地方.

有些bean會被適用於它的bpp去處理去生成或者去注入屬性.而有一些可能就是比較原生,直接通過bd被BeanWrapper給new出來.

 

 

3.prepareBeanFactory

 1     /**
 2      * Configure the factory's standard context characteristics,
 3      * such as the context's ClassLoader and post-processors.
 4      * @param beanFactory the BeanFactory to configure
 5      */
 6     protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
 7         // Tell the internal bean factory to use the context's class loader etc.
 8         beanFactory.setBeanClassLoader(getClassLoader());
 9         beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
10         beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
11 
12         // Configure the bean factory with context callbacks.
13         beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
14         beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
15         beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
16         beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
17         beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
18         beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
19 
20         // BeanFactory interface not registered as resolvable type in a plain factory.
21         // MessageSource registered (and found for autowiring) as a bean.
22         beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
23         beanFactory.registerResolvableDependency(ResourceLoader.class, this);
24         beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
25         beanFactory.registerResolvableDependency(ApplicationContext.class, this);
26 
27         // Detect a LoadTimeWeaver and prepare for weaving, if found.
28         if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
29             beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
30             // Set a temporary ClassLoader for type matching.
31             beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
32         }
33 
34         // Register default environment beans.
35         if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
36             beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
37         }
38         if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
39             beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
40         }
41         if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
42             beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
43         }
44     }

大致做的事情就是

 

3.1 SPEL

設置spelResolver用於spel的解析. spel單獨就有一個自己的模塊. 具體就不說了.

 

3.2 PropertyEditorRegistrar

設置PropertyEditorRegistrar. spring的配置文件很多都是XML或者property這種文本.讀取出來的都是字符串.但是java對象有各種類型的屬性.所以生成bean的時候需要做一些類型轉化

比如 String -> Int類似這種, 就需要自己去寫一個PropertyEditorSupport的實現類,去impl setAsText(String) 的方法.把XML里得到的字符串轉化成Java對象里的Int值.Spring自帶了很多這種Editor

 

ResourceEditorRegistrar.java

 

 

 

另外spring的類型轉化也有很多種方法.這種PropertyEditorSupport(java.beans包下的)可能是早期的方案.后續的SPring版本中有一些地方轉化用到了conversionService. 里面又設計到其他的一些類型轉化接口.

可以參考我的這篇文章
https://www.cnblogs.com/abcwt112/p/7447435.html

 

3.3 注冊BeanPostProcessor

beanPostProcessor可以在bean初始化方法(比如XML里的init-method或者InitializingBean的afterPropertySet方法)前和后對bean進行加工或者返回一個wrapper替換掉原本的bean.

注意的是bean的屬性填充是在bpp2個操作之前的.就是populate(BeanFactory創建bean的一個利用BeanWrapper去設置bean的屬性的時候回調用的方法)方法已經被調用過的.

Spring在這里new了一個ApplicationContextAwareProcessor

 1     @Override
 2     public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
 3         AccessControlContext acc = null;
 4 
 5         if (System.getSecurityManager() != null &&
 6                 (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
 7                         bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
 8                         bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
 9             acc = this.applicationContext.getBeanFactory().getAccessControlContext();
10         }
11 
12         if (acc != null) {
13             AccessController.doPrivileged(new PrivilegedAction<Object>() {
14                 @Override
15                 public Object run() {
16                     invokeAwareInterfaces(bean);
17                     return null;
18                 }
19             }, acc);
20         }
21         else {
22             invokeAwareInterfaces(bean);
23         }
24 
25         return bean;
26     }
27 
28     private void invokeAwareInterfaces(Object bean) {
29         if (bean instanceof Aware) {
30             if (bean instanceof EnvironmentAware) {
31                 ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
32             }
33             if (bean instanceof EmbeddedValueResolverAware) {
34                 ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
35                         new EmbeddedValueResolver(this.applicationContext.getBeanFactory()));
36             }
37             if (bean instanceof ResourceLoaderAware) {
38                 ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
39             }
40             if (bean instanceof ApplicationEventPublisherAware) {
41                 ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
42             }
43             if (bean instanceof MessageSourceAware) {
44                 ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
45             }
46             if (bean instanceof ApplicationContextAware) {
47                 ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
48             }
49         }
50     }
View Code

對實現了一部分Aware的bean做方法調用.

比如你的bean impl了ApplicationContextAware這個接口.那就會調用你的setApplicationContext方法去讓你有機會將ac設置為你的bean里的一個屬性.

為什么Aware的一些接口要用這些內置的bpp去處理,而不是當做一般的bean注入?

我個人覺得是第一,要控制是什么時候注入這些bean.比如如果只是在一般的populate屬性的時候注入這個ac.那這個時候不是所有的bean都被new過..可能會有一些意想不到的問題.

第二我覺得是因為ac和BeanFactory可能會有多個,比如早期沒有springboot的時候.spring會有一個ac.然后springmvc自己也會有一個ac.有parent和child的關系.那你在一個bean里注入ac.就會有2個符合條件的ac選擇.這也是有問題的.

 

3.4 忽略部分類型bean的注入

1         beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
2         beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
3         beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
4         beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
5         beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
View Code

為什么這些類型的bean不需要注入? 因為3.3里已經在bpp里處理了

 

3.5 指定部分類型的bean注入

1         beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
2         beanFactory.registerResolvableDependency(ResourceLoader.class, this);
3         beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
4         beanFactory.registerResolvableDependency(ApplicationContext.class, this);
View Code

指定了一些bean的類型使用特定的bean注入..比如BeanFactory就使用當前這個ac對應的bf去注入即可.

 

3.6 額外注冊一些Bean

 1         // Detect a LoadTimeWeaver and prepare for weaving, if found.
 2         if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
 3             beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
 4             // Set a temporary ClassLoader for type matching.
 5             beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
 6         }
 7 
 8         // Register default environment beans.
 9         if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
10             beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
11         }
12         if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
13             beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
14         }
15         if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
16             beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
17         }
View Code

如果有一些bean你沒配置.那就會使用spring默認的配置.比如environment.你如果配置了.那就用你的bean

 

4. postProcessBeanFactory(beanFactory);

這個方法是一個模板方法,允許子類對bf做一些處理.

比如一些web相關的ac會在這里add一些bpp比如ServletContextAwareProcessor來對servlet做一些處理

或者在這里也可以get BF以后去調用方法增加一些BeanFactoryPostProcessor.

 

5.invokeBeanFactoryPostProcessors(beanFactory);

做到這個方法的時候BF已經加載完所有的BeanDifination了(詳見第2節).但是任何bean都還沒有被初始化(new).

看方法名字就知道這個方法是去激活調用beanFactoryPostProcessors的相關方法的.

beanFactoryPostProcessors這個接口還有一個子接口叫做BeanDefinitionRegistryPostProcessor.

這個子接口的postProcessBeanDefinitionRegistry方法是處理BeanDefinitionRegistry用的.可能是個新增的接口.因為我看到網上很多博客上都只寫了BFPP而沒有寫這個接口..(因為大部分文章介紹的是早期的spring)

這個接口的會先於BFPP的postProcessBeanFactory掉用,他可以處理BeanDefinitionRegistry,有一些BF實現了這個接口,也有一些BF沒有.絕大部分大部分ac使用的DefaultListableBeanFactory

是實現了這個接口的.所以可以處理BeanDefinitionRegistryPostProcessor.

 

BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry作用是給你一個機會去手動注冊beanDifination..可以用這個接口去注冊一些BeanFactoryPostProcessor..當然普通的BD也可以去注冊或者修改.但是如果是這種目的的話最好可以使用BeanFactoryPostProcessor的postProcessBeanFactory.這樣通用性更好.也更合理.

 

BeanFactoryPostProcessor的postProcessBeanFactory用於修改BeanFactory或者去修改BF里的BeanDifination..

一個典型的案例就是在早期版本的spring(還沒用springboot的時候)我們會配置placeholderconfigurer.這個類就是實現了BeanFactoryPostProcessor接口.他會掃描所有bean里的屬性.去把${}這種占位符替換成property文件里指定的值.常用於db的配置獨立放在.properties文件中,datasource的配置放在bean.XML文件中. 

 

所以invokeBeanFactoryPostProcessors(beanFactory);這個方法所做的事情就是.

1.獲取所有手動注冊的BeanDefinitionRegistryPostProcessor.去調用postProcessBeanDefinitionRegistry.

所謂的手動注冊就是在之前幾節的模板方法中直接調用ApplicationContext的addBeanFactoryPostProcessor方法注冊的BeanDefinitionRegistryPostProcessor

 

2.然后獲取掃描bf中所有注冊的BeanDefinitionRegistryPostProcessor.

按PriorityOrdered > Ordered > rest 去排序,依次調用postProcessBeanDefinitionRegistry方法

也就是說你的非手動注冊的BeanDefinitionRegistryPostProcessor如果實現了PriorityOrdered接口.那肯定會比實現了Ordered接口的BeanDefinitionRegistryPostProcessor早調用.

同樣接口的.就按接口內定義的順序排序.比如Ordered接口.就是數字越小排在越前面

 

3.處理一般的BeanFactoryPostProcessor的postProcessBeanFactory方法.

順序和BeanDefinitionRegistryPostProcessor一樣,也是 手動注冊的> PriorityOrdered > Ordered > rest

 

  1 public static void invokeBeanFactoryPostProcessors(
  2             ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
  3 
  4         // Invoke BeanDefinitionRegistryPostProcessors first, if any.
  5         Set<String> processedBeans = new HashSet<String>();
  6 
  7         if (beanFactory instanceof BeanDefinitionRegistry) {
  8             BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
  9             List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
 10             List<BeanDefinitionRegistryPostProcessor> registryPostProcessors =
 11                     new LinkedList<BeanDefinitionRegistryPostProcessor>();
 12 
 13             for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
 14                 // 特殊的BeanDefinitionRegistryPostProcessor的,比如處理@configuration.注冊bd
 15                 if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
 16                     BeanDefinitionRegistryPostProcessor registryPostProcessor =
 17                             (BeanDefinitionRegistryPostProcessor) postProcessor;
 18                     registryPostProcessor.postProcessBeanDefinitionRegistry(registry);
 19                     registryPostProcessors.add(registryPostProcessor);
 20                 }
 21                 else {
 22                     regularPostProcessors.add(postProcessor);
 23                 }
 24             }
 25 
 26             // Do not initialize FactoryBeans here: We need to leave all regular beans
 27             // uninitialized to let the bean factory post-processors apply to them!
 28             // Separate between BeanDefinitionRegistryPostProcessors that implement
 29             // PriorityOrdered, Ordered, and the rest.
 30             String[] postProcessorNames =
 31                     beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
 32 
 33             // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
 34             List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
 35             for (String ppName : postProcessorNames) {
 36                 if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
 37                     priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
 38                     processedBeans.add(ppName);
 39                 }
 40             }
 41             sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
 42             registryPostProcessors.addAll(priorityOrderedPostProcessors);
 43             invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);
 44 
 45             // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
 46             postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
 47             List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
 48             for (String ppName : postProcessorNames) {
 49                 if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
 50                     orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
 51                     processedBeans.add(ppName);
 52                 }
 53             }
 54             sortPostProcessors(beanFactory, orderedPostProcessors);
 55             registryPostProcessors.addAll(orderedPostProcessors);
 56             invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry);
 57 
 58             // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
 59             boolean reiterate = true;
 60             while (reiterate) {
 61                 reiterate = false;
 62                 postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
 63                 for (String ppName : postProcessorNames) {
 64                     if (!processedBeans.contains(ppName)) {
 65                         BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class);
 66                         registryPostProcessors.add(pp);
 67                         processedBeans.add(ppName);
 68                         pp.postProcessBeanDefinitionRegistry(registry);
 69                         reiterate = true;
 70                     }
 71                 }
 72             }
 73 
 74             // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
 75             invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory);
 76             invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
 77         }
 78 
 79         else {
 80             // Invoke factory processors registered with the context instance.
 81             invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
 82         }
 83 
 84         // Do not initialize FactoryBeans here: We need to leave all regular beans
 85         // uninitialized to let the bean factory post-processors apply to them!
 86         String[] postProcessorNames =
 87                 beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
 88 
 89         // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
 90         // Ordered, and the rest.
 91         List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
 92         List<String> orderedPostProcessorNames = new ArrayList<String>();
 93         List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
 94         for (String ppName : postProcessorNames) {
 95             if (processedBeans.contains(ppName)) {
 96                 // skip - already processed in first phase above
 97             }
 98             else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
 99                 priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
100             }
101             else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
102                 orderedPostProcessorNames.add(ppName);
103             }
104             else {
105                 nonOrderedPostProcessorNames.add(ppName);
106             }
107         }
108 
109         // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
110         sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
111         invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
112 
113         // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
114         List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
115         for (String postProcessorName : orderedPostProcessorNames) {
116             orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
117         }
118         sortPostProcessors(beanFactory, orderedPostProcessors);
119         invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
120 
121         // Finally, invoke all other BeanFactoryPostProcessors.
122         List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
123         for (String postProcessorName : nonOrderedPostProcessorNames) {
124             nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
125         }
126         invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
127     }
View Code

 

 

6.registerBeanPostProcessors(beanFactory);

注冊BPP.

之前是BFPP用於處理BeanFactory,處理其中的BeanDifination.那這里就是注冊BPP用於在處理bean了.

對於BPP並沒有手動注冊的方法..比如ac的addBeanPostProcessor這種方法..BFPP相關方法的調用是先於bean 初始化(new)的,很好理解,因為是對BeanFactory的處理,而不是當bean的處理.. (但是BFPP也是會在bean new之前全部被掃描從bf里找出來特殊處理...所以從這點上說好像不用手動配置也可以..)

而bpp是在bean 初始化或者填充屬性過程中處理的.是在bean被new的過程中處理的...沒必要手動注冊...因為當前這一步僅僅是添加bpp..還不會調用bpp的相關方法(因為這個時候還沒有new bean)...這一點BFPP不同(BFPP直接調用相關方法).直接和一般的bean一樣配置就行了.

 

BPP的處理順序和BFPP一樣(再次強調一下,這里只是把這些BPP的特殊的bean new出來了.並不會new 一般的bean.所以這里不會調用BPP的相關方法).最后就是BPP也有特殊的子接口,叫做MergedBeanDefinitionPostProcessor,是最后處理的.所以這些MergedBeanDefinitionPostProcessor會在BPP的最內層.(如果只是當做一般的BPP去使用相關方法的話就不要使用這個子接口.因為會影響處理的順序..)

 

7.initMessageSource

初始化MessageSource,主要用於國際化.沒怎么用過.沒深入研究..大致是讀取不同語言的properties根據Locale去做相應的處理.

 

8.initApplicationEventMulticaster

同7個人沒咋用過.

ApplicationContext可以publish一些Event.你也可以注冊一些Listener去監聽自己感興趣的實踐.

 

9.onRefresh();

也是一個模板方法.給子類ac一個機會去初始化自己想要初始化的特殊的bean

比如一些web的ac會初始化ThemeSource...用於web頁面的主題展示和切換...比如jsp里的標簽:<spring:theme code="style"/>

現在前后端分離了這個感覺很少用了...

 

10.registerListeners();

配合8.可以注冊一些listener去監聽你感興趣的ApplicationEvent

 

11.finishBeanFactoryInitialization(beanFactory);

除了注冊一些特殊的bean.比如ConversionService以外.

最重要的就是對於之前BF加載的每一個BD.如果這個bean是單例並且不是lazy的.不是abstract的(XML里可以配置一個bean是abstract.用於繼承簡化配置),就去初始化對應的bean.也就是通過BeanFactory.doGetBean方法去創建這個bean的實例..

里面涉及比較復雜的步驟...涉及各種BPP的調用,還有各種情況的處理...比如循環依賴, 代理方法什么的.....后面會再分享..

 

12.finishRefresh()

完成refresh.個人沒怎么用過.

會注冊LifecycleProcessor.如果你的bean實現了Lifecycle接口.在ac做stop.refresh或者start等方法的時候你的bean也會被調用這些方法給你一些回調處理的機會.

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM