主題
學習記錄一下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 }
這個方法基本啥都沒做.留給子類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 }
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 }
對實現了一部分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);
為什么這些類型的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);
指定了一些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 }
如果有一些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 }
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也會被調用這些方法給你一些回調處理的機會.
