spring Bean載入過程
spring Bean載入過程
1、找准入口 ,使用ClassPathXmlApplicationContext載入配置檔案,用於載入classPath下的配置檔案
//第一行,執行完成之後就完成了spring配置檔案的載入,重新整理spring上下文 ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext( "classpath:spring-mvc.xml"); //獲取例項Bean Person person=context.getBean("person",Person.class);
ClassPathXmlApplicationContext的繼承關係如下:

https://images2015.cnblogs.com/blog/801753/201702/801753-20170201125310058-568989522.png
2、現在開始仔細分析第一句,可以看出第一句就已經完成了spring配置檔案的載入
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext( "classpath:spring-mvc.xml");
3、檢視classPathXmlApplicationContext的原始碼,下面表格是物件
物件名 | 類 型 | 作 用 | 歸屬類 |
---|---|---|---|
configResources | Resource[] | 配置檔案資源物件陣列 | ClassPathXmlApplicationContext |
configLocations | String[] | 配置檔案字串陣列,儲存配置檔案路徑 | AbstractRefreshableConfigApplicationContext |
beanFactory | DefaultListableBeanFactory | 上下文使用的Bean工廠 | AbstractRefreshableApplicationContext |
beanFactoryMonitor | Object | Bean工廠使用的同步監視器 | AbstractRefreshableApplicationContext |
id | String | 上下文使用的唯一Id,標識此ApplicationContext | AbstractApplicationContext |
parent | ApplicationContext | 父級ApplicationContext | AbstractApplicationContext |
beanFactoryPostProcessors | List<BeanFactoryPostProcessor> |
儲存BeanFactoryPostProcessor介面,Spring提供的一個擴充套件點 | AbstractApplicationContext |
startupShutdownMonitor | Object | refresh方法和destory方法公用的一個監視器,避免兩個方法同時執行 | AbstractApplicationContext |
shutdownHook | Thread | Spring提供的一個鉤子,JVM停止執行時會執行Thread裡面的方法 | AbstractApplicationContext |
resourcePatternResolver | ResourcePatternResolver | 上下文使用的資源格式解析器 | AbstractApplicationContext |
lifecycleProcessor | LifecycleProcessor | 用於管理Bean生命週期的生命週期處理器介面 | AbstractApplicationContext |
messageSource | MessageSource | 用於實現國際化的一個介面 | AbstractApplicationContext |
applicationEventMulticaster | ApplicationEventMulticaster | Spring提供的事件管理機制中的事件多播器介面 | AbstractApplicationContext |
applicationListeners | Set<ApplicationListener> | Spring提供的事件管理機制中的應用監聽器 | AbstractApplicationContext |
4、從構造方法可以看出,載入spring配置檔案實際呼叫的是如下構造方法:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { //設定父級的ApplicationContext,null super(parent); //1.設定配置檔案的路徑, 2. 將路徑中的佔位符${placeholder}使用系統的變數替換 setConfigLocations(configLocations); if (refresh) { refresh(); } }
5、進入setConfigLocations(configLocations);的原始碼,這個方法是父類AbstractRefreshableConfigApplicationContext中的方法
1. 設定配置檔案的路徑 2. 替換路徑中的佔位符`${placeholder}`為系統變數中的值
//locations : 配置檔案路徑-+ public void setConfigLocations(String[] locations) { if (locations != null) { //斷言 Assert.noNullElements(locations, "Config locations must not be null"); //儲存配置檔案路徑的陣列,儲存去掉佔位符後的檔案路徑陣列 this.configLocations = new String[locations.length]; //遍歷locations,解析佔位符 for (int i = 0; i < locations.length; i++) { //呼叫resolvePath解析佔位符 this.configLocations[i] = resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } }
6、進入resolvePath的原始碼可以知道,實際上執行的是AbstractPropertyResolver的doResolvePlaceholders方法,如下
/** * text : 需要解析的路徑 * PropertyPlaceholderHelper : 這個是解析系統佔位符的輔助類,主要用來將佔位符替換成系統的環境變數 */ private String doResolvePlaceholders(String text, PropertyPlaceholderHelper helper) { //呼叫PropertyPlaceholderHelper類中的replacePlaceholders方法 return helper.replacePlaceholders(text, new PropertyPlaceholderHelper.PlaceholderResolver() { public String resolvePlaceholder(String placeholderName) { return getPropertyAsRawString(placeholderName); } }); }
7、 進入 PropertyHelpe
r中的 replacePlaceholders
方法 ,實際上呼叫 org.springframework.util.PropertyPlaceholderHelper
這個類的 parseStringValue
解析佔位符
- 實際呼叫的是 parseStringValue 方法
- this.placeholderPrefix這個是佔位符的字首
{" ,placeholderSuffix="}",valueSeparator=":"
- 使用parseStringValue方法遞迴解析佔位符中的內容
- 在
parseStringValue
方法中使用兩次遞迴-
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
,這個是第一次,用來解析佔位符中的placeholder是否還包含佔位符,如果有佔位符需要將其抽離出來,去掉${}
-
propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
,這個是第二次遞迴呼叫,用來解析propVal
中的佔位符
-
public String replacePlaceholders(String value, PlaceholderResolver placeholderResolver) { Assert.notNull(value, "Argument 'value' must not be null."); //呼叫的是parseStringValue方法 return parseStringValue(value, placeholderResolver, new HashSet<String>()); } /** * strVal: 需要解析的字串,就是配置檔案的路徑 * placeholderResolver : 策略介面,佔位符解析器 * visitedPlaceholders : 儲存已經訪問過的佔位符 **/ protected String parseStringValue( String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) { //將strval轉換成StringBuilder,便於後續到操作 StringBuilder buf = new StringBuilder(strVal); //this.placeholderPrefix這個是佔位符的字首 ${,在建立PropertyHelper的時候就已經指定了佔位符的placeholderPrefix="${" ,placeholderSuffix="}",valueSeparator=":" //獲取字首在這個配置檔案路徑中的開始索引 int startIndex = strVal.indexOf(this.placeholderPrefix); while (startIndex != -1) { //佔位符字首在路徑中的結束索引 int endIndex = findPlaceholderEndIndex(buf, startIndex); //如果結束索引存在 if (endIndex != -1) { //此時取出${plcaeholder}中的佔位符內容placeholder String placeholder = buf.substring(startIndex + this.placeholderPrefix.length(), endIndex); //儲存取出來的佔位符內容placeholder String originalPlaceholder = placeholder; //如果佔位符中的內容已經被訪問過了,丟擲出異常返回,遞迴結束的條件 if (!visitedPlaceholders.add(originalPlaceholder)) { throw new IllegalArgumentException( "Circular placeholder reference '" + originalPlaceholder + "' in property definitions"); } //遞迴解析已經取出的佔位符中的內容 palceholder placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders); //這個最重要的一步,將解析佔位符內容placeholder的值,比如將java.version轉換成1.8.0_60 String propVal = placeholderResolver.resolvePlaceholder(placeholder); if (propVal == null && this.valueSeparator != null) { int separatorIndex = placeholder.indexOf(this.valueSeparator); if (separatorIndex != -1) { String actualPlaceholder = placeholder.substring(0, separatorIndex); String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length()); propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder); if (propVal == null) { propVal = defaultValue; } } } //如果解析出來的佔位符不為空,比如${java.version}將被解析成 1.8.0_60 if (propVal != null) { //此時繼續遞迴解析出1.8.0_60中的佔位符 propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders); //將路徑中的佔位符替換成系統變數的值,比如將${java.version} 替換成 1.8.0_60 buf.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal); if (logger.isTraceEnabled()) { logger.trace("Resolved placeholder '" + placeholder + "'"); } //繼續在路徑字串中剩餘的子串中查詢佔位符,如果有佔位符,那麼還會繼續解析佔位符 startIndex = buf.indexOf(this.placeholderPrefix, startIndex + propVal.length()); } else if (this.ignoreUnresolvablePlaceholders) { // Proceed with unprocessed value. startIndex = buf.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length()); } else { throw new IllegalArgumentException("Could not resolve placeholder '" + placeholder + "'" + " in string value \"" + strVal + "\""); } //將已轉換成功的佔位符從以訪問的集合中移除即可 visitedPlaceholders.remove(originalPlaceholder); } else { startIndex = -1; } } return buf.toString();//將解析完成之後的配置檔案返回 }
8、總之一句話 : setConfigLocations(configLocations);的作用就是將客戶端傳入的配置檔案路徑,先解析佔位符,之後將解析完成之後的配置檔案路徑儲存起來
9、現在進入ClassPathXmlApplicationContext中的refresh方法,實際上呼叫的是父類org.springframework.context.support.AbstractApplicationContext的方法,下面我們一個一個方法分析
//重新整理spring上下文 public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { //在重新整理之前設定一些引數,比如設定開始時間戳,上下文是否啟用的標誌,輸出重新整理上下文的資訊,驗證一些必要的屬性 prepareRefresh(); //需要建立beanFactory,如果已經存在beanFactory,那麼關閉,詳細其請看 10 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 準備上下文工廠,詳情見12 prepareBeanFactory(beanFactory); try { //允許子類向後置處理器新增元件 postProcessBeanFactory(beanFactory); // 呼叫BeanFactoryPostProcessor和BeanDefintionRegistoryPostProcessor這兩個後置處理器 invokeBeanFactoryPostProcessors(beanFactory); // 註冊BeanPostProcessor,用來攔截bean的建立,詳情見 14 registerBeanPostProcessors(beanFactory); //初始化訊息源 initMessageSource(); // 初始化應用程式事件廣播器,使用者可以自定義一個事件廣播器,如果使用者沒有定義,那麼使用預設的事件廣播器SimpleApplicationEventMulticaster initApplicationEventMulticaster(); // 在其他子類中初始化bean onRefresh(); // 檢測事件監聽器 registerListeners(); //完成例項化剩餘的單例(non-lazy-init) finishBeanFactoryInitialization(beanFactory); // 完成重新整理,初始化生命週期處理器...... finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
10、進入 obtainFreshBeanFactory
,分析原始碼
//AbastractApplicationContext的方法 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { //實際重新整理上下文的方法,這個方法就是實際的重新整理上下文方法,其中會呼叫loadBeanDefinitions(beanFactory);載入配置檔案中的內容到BeanDefiniton中 refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; } //org.springframework.context.support.AbstractRefreshableApplicationContext中的方法 //AbstractApplicationContext的子類中的方法 @Override protected final void refreshBeanFactory() throws BeansException { //如果其中有beanfactory,那麼銷燬 if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { //重新建立一個beanFactory DefaultListableBeanFactory beanFactory = createBeanFactory(); //設定序列化id beanFactory.setSerializationId(getId()); //定製beanFactory,設定相關屬性,包括是否允許覆蓋名稱的不同定義的物件及迴圈依賴以及 //設定@Autowired和@Qualifier,註解解析器QualifierAnnotationAutowireCandidateResolver customizeBeanFactory(beanFactory); //載入BeanDefine 詳情見11 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
11、 進入 loadBeanDefinitions(beanFactory);
方法
1、 主要呼叫的是XmlBeanDefinitionReader其中的loadBeanDefinitions方法,詳情請看我的spring之BeanDefinitonReader解析
//這個是org.springframework.context.support.AbstractXmlApplicationContext類中的方法 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { //建立要給beanDefinitionReader,用於讀取BeanDefinition //詳情見 BeanDefinitonReader的原始碼解析 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); //配置XmlBeanDefinitionReader beanDefinitionReader.setEnvironment(this.getEnvironment()); beanDefinitionReader.setResourceLoader(this); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); initBeanDefinitionReader(beanDefinitionReader); //載入BeanDefiniton,主要的功能從配置檔案中讀取BeanDefiniton註冊到登錄檔中 loadBeanDefinitions(beanDefinitionReader); }
12、prepareBeanFactory :準備BeanFactory,目前還不太明白,後續分析
//準備BeanFactory,設定一些引數,比如後置處理器, protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { //設定類載入器 beanFactory.setBeanClassLoader(getClassLoader()); //設定表示式解析器,用來解析BeanDefiniton中的帶有表示式的值 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 配置後置處理器,主要的作用就是在spring例項化bean的前後做一些操作 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); //忽略自動裝配的類,這些類都不能使用@Resource或者@Autowired自動裝配獲取物件 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); //註冊可解析的自動裝配類 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); //在新增一個應用程式監聽器 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); //檢查這些類是否被 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // 將下面這些類註冊到容器中,使用registerSingleton方法註冊,我們可以直接從容器中獲取這些類的物件使用 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }
13、呼叫BeanFactory的後置處理器,主要的功能就是呼叫註冊在容器中的BeanFactoryPostProcessor和BeanDefinitionRegistoryPostProcessor
1、 BeanFactoryPostProcessor 這個是後置處理器,實現這個類可以修改容器中bean的資料資訊,可以在spring配置檔案載入之後執行,在單例例項化之前呼叫,因此可以在其中修改和獲取bean的例項化的資訊,通過 BeanDefintion
2、先呼叫 BeanDefinitionRegistryPostProcessor ,按照優先順序呼叫,比如分為實現PriorityOrdered這個介面和Orderd這個介面的,分開呼叫
3、再呼叫實現BeanFactoryPostProcessor這個介面的,也是按照優先級別呼叫,和上面的流程一樣
//例項化和呼叫BeanFactory後置處理器,必須在單例例項化之前呼叫 protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { //呼叫後置處理器註冊委託類的方法呼叫,getBeanFactoryPostProcessors用於獲取註冊的全部的BeanFactoryPostProcessor PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); } //實際的呼叫方法,PostProcessorRegistrationDelegate中的方法 public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any. Set<String> processedBeans = new HashSet<String>(); //如果beanFactory是BeanDefinitionRegistry的子類,BeanDefinitionRegistry使用來向登錄檔中註冊Bean的元資訊的(BeanDefintion) if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; //存放BeanFactoryPostProcessor List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); //存放BeanDefinitionRegistryPostProcessor List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); //遍歷。判斷是否是BeanDefinitionRegistryPostProcessor例項 for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; //呼叫BeanDefinitionRegistryPostProcessor registryPostProcessor.postProcessBeanDefinitionRegistry(registry); //新增 registryPostProcessors.add(registryPostProcessor); } else { //表示這個是BeanFactoryPostProcessor例項,新增進集合 regularPostProcessors.add(postProcessor); } } //--- 根據型別型別獲取beanFactory中註冊的BeanDefinitionRegistryPostProcessor的bean的所有名稱陣列 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); // ---- 首先呼叫的是BeanDefinitionRegistryPostProcessor型別的後置處理器 //存放實現PriorityOrdered這個介面的BeanDefinitionRegistryPostProcessor List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); //遍歷,如果實現了PriorityOrdered這個介面就儲存下來 for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } //按照優先順序排序 OrderComparator.sort(priorityOrderedPostProcessors); //新增進入集合 registryPostProcessors.addAll(priorityOrderedPostProcessors); //首先呼叫實現PriorityOrdered這個介面的BeanDefinitionRegistryPostProcessor invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry); // ---- 下面是呼叫實現Orderd這個介面的BeanDefinitionRegistryPostProcessor postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); List<BeanDefinitionRegistryPostProcessor> orderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } OrderComparator.sort(orderedPostProcessors); registryPostProcessors.addAll(orderedPostProcessors); invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors, registry); // ---- 最終呼叫剩餘全部的BeanDefinitionRegistryPostProcessor boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); for (String ppName : postProcessorNames) { if (!processedBeans.contains(ppName)) { BeanDefinitionRegistryPostProcessor pp = beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class); registryPostProcessors.add(pp); processedBeans.add(ppName); pp.postProcessBeanDefinitionRegistry(registry); reiterate = true; } } } // 呼叫BeanFactoryPostProcessor介面中的方法,因為BeanDefitionRegistory繼承了這個介面 invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // Invoke factory processors registered with the context instance. invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } //--- 下面是呼叫實現BeanFactoryPostProcessor介面的類,和上面的流程一樣 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // Separate between BeanFactoryPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); List<String> orderedPostProcessorNames = new ArrayList<String>(); List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); for (String ppName : postProcessorNames) { if (processedBeans.contains(ppName)) { // skip - already processed in first phase above } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. OrderComparator.sort(priorityOrderedPostProcessors); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // Next, invoke the BeanFactoryPostProcessors that implement Ordered. List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } OrderComparator.sort(orderedPostProcessors); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // Finally, invoke all other BeanFactoryPostProcessors. List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); }
14、註冊BeanPostProcessor,用來攔截Bean的建立,這個介面可以實現在Bean初始化和初始化之後執行相關的操作,會有單獨一篇解讀
1、這個註冊BeanPostProcessor思想和上面的呼叫BeanFactoryPostProcessor的思想一樣,按照優先順序註冊,通過判斷是否實現PriorityOrdered和orderd介面,按照優先順序排序註冊到BeanFactory中,其實註冊的方法就是將這個後置處理器新增到beanFactory中的 List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>()
//依然這裡依然呼叫的PostProcessorRegistrationDelegate,其中包含了註冊後置處理器和呼叫後置處理器的方法,相當於一個代理人 protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); } //PostProcessorRegistrationDelegate中的註冊BeanPostProcessors的方法 //其中beanFactory這個新建立的beanFactory,其中的BeanPostProcessor都沒有註冊,applicationContext這個是之前建立的,其中的處理器已經註冊過了 public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { //根據型別新載入全部的BeanFactoryProcessor的類, String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); //建立BeanPostProcessor檢測器 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // Separate between BeanPostProcessors that implement PriorityOrdered, // Ordered, and the rest. List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>(); List<String> orderedPostProcessorNames = new ArrayList<String>(); List<String> nonOrderedPostProcessorNames = new ArrayList<String>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); priorityOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { orderedPostProcessorNames.add(ppName); } else { nonOrderedPostProcessorNames.add(ppName); } } // First, register the BeanPostProcessors that implement PriorityOrdered. OrderComparator.sort(priorityOrderedPostProcessors); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // Next, register the BeanPostProcessors that implement Ordered. List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>(); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } OrderComparator.sort(orderedPostProcessors); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // Now, register all regular BeanPostProcessors. List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>(); for (String ppName : nonOrderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); nonOrderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors); // Finally, re-register all internal BeanPostProcessors. OrderComparator.sort(internalPostProcessors); registerBeanPostProcessors(beanFactory, internalPostProcessors); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
總結
1、入口
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("spring-test.xml");
2、解析傳入的路徑中的佔位符,集合 org.springframework.core.env.AbstractPropertyResolver
和 org.springframework.util.PropertyPlaceholderHelper
3、重新整理上下文
1、 prepareRefresh()
: 準備重新整理,設定一些活動標誌,比如開始時間,當前的狀態
2、 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
:從spring的配置檔案中載入bean,封裝成BeanDefinition,註冊到登錄檔中,建立beanFactory
3、 prepareBeanFactory(beanFactory);
:準備BeanFactory,設定累載入器,新增後置處理器,SPL表示式解析器,向ioc容器中注入一些元件
4、 postProcessBeanFactory(beanFactory);
: 允許子類做一些處理操作
5、 invokeBeanFactoryPostProcessors(beanFactory);
:呼叫BeanFactoryProcessor,先是呼叫BeanDefitionRegistoyPostProcessor,之後呼叫BeanFactoryProcessor
6、 registerBeanPostProcessors(beanFactory);
: 將配置檔案中讀取的Bean的後置處理器註冊到容器中
7、 initMessageSource();
:初始化訊息源,用於國際化
8、 initApplicationEventMulticaster()
: 初始化事件廣播器,判斷容器中是否已經註冊了該元件,如果沒有該元件,那麼使用預設的
9、 onRefresh();
:子類初始化一些特殊的bean
10、 registerListeners();
:註冊事件監聽器
11、 finishBeanFactoryInitialization(beanFactory)
:完成初始化,初始化非懶載入的bean
12、 finishRefresh();
:完成重新整理,最後一步,初始化生命週期處理器,派發事件
參考文章
- ofollow,noindex">https://blog.csdn.net/turkeyzhou/article/category/365505/2
- https://www.evget.com/article/2016/2/23/23576.html
- http://www.cnblogs.com/killbug/p/6087648.html