麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

Spring4.3.x 容器的刷新過程

2019-11-10 20:17:56
字體:
來源:轉載
供稿:網友

概述


SPRing容器體系的繼承結構圖如下。

這里寫圖片描述

從圖中可以看出抽象類AbstractapplicationContext是所有容器類的父類。AbstractApplicationContext實現了它繼承的所有接口方法,并定義了三個用于管理BeanFactory對象的抽象方法,如下

//--------------------------------------------------------------------- // Abstract methods that must be implemented by subclasses //--------------------------------------------------------------------- /** * Subclasses must implement this method to perform the actual configuration load. * The method is invoked by {@link #refresh()} before any other initialization work. * <p>A subclass will either create a new bean factory and hold a reference to it, * or return a single BeanFactory instance that it holds. In the latter case, it will * usually throw an IllegalStateException if refreshing the context more than once. * @throws BeansException if initialization of the bean factory failed * @throws IllegalStateException if already initialized and multiple refresh * attempts are not supported */ protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException; /** * Subclasses must implement this method to release their internal bean factory. * This method gets invoked by {@link #close()} after all other shutdown work. * <p>Should never throw an exception but rather log shutdown failures. */ protected abstract void closeBeanFactory(); /** * Subclasses must return their internal bean factory here. They should implement the * lookup efficiently, so that it can be called repeatedly without a performance penalty. * <p>Note: Subclasses should check whether the context is still active before * returning the internal bean factory. The internal factory should generally be * considered unavailable once the context has been closed. * @return this application context's internal bean factory (never {@code null}) * @throws IllegalStateException if the context does not hold an internal bean factory yet * (usually if {@link #refresh()} has never been called) or if the context has been * closed already * @see #refreshBeanFactory() * @see #closeBeanFactory() */ @Override public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

小技巧:告訴大家如何查看一個抽象類未實現的接口方法有哪些,比如上面的AbstractApplicationContext抽象類。我創建了一個MyApplicationContext 類,如果未實現任何方法,IDE會提醒我實現父類中未實現的方法,代碼如下。

public class MyApplicationContext extends AbstractApplicationContext { @Override protected void refreshBeanFactory() throws BeansException, IllegalStateException { } @Override protected void closeBeanFactory() { } @Override public ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException { return null; }}

回歸正題,Spring容器在初始化的時候都會執行一個方法來結束初始化,那就是refresh()方法,此方法定義在接口ConfigurableApplicationContext中,并且抽象類AbstractApplicationContext實現了它,代碼如下

@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 為容器的刷新做準備工作,設置啟動日期,更新活動標志,加載屬性資源 prepareRefresh(); // 獲取最新的bean工廠對象。 // 要求子類刷新自身持有的bean工廠對象 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // 在容器使用bean工廠之前,設置bean工廠 // 主要是添加特定的bean后處理器 prepareBeanFactory(beanFactory); try { // 鉤子方法,允許在子類中bean工廠做進一步的處理 // 子類可以根據自身需要,添加更多的bean后處理器 postProcessBeanFactory(beanFactory); // 在上下文容器中執行所有注冊了的bean工廠后處理器 // 執行步驟:1. 在bean工廠中找到所有實現了BeanFactoryPostProcessor的對象 // ->2. 執行所有bean工廠后處理器的postProcessBeanFactory方法 invokeBeanFactoryPostProcessors(beanFactory); // 把所有用戶配置的bean后處理器添加到bean工廠中 registerBeanPostProcessors(beanFactory); // 初始化國際化消息對象,默認為DelegatingMessageSource initMessageSource(); // 初始化事件傳播器,默認為SimpleApplicationEventMulticaster initApplicationEventMulticaster(); // 鉤子方法,初始化其他特定的bean onRefresh(); // 注冊用戶指定的和容器創建時添加的監聽器 registerListeners(); // 初始化所有剩下的單例非延遲bean finishBeanFactoryInitialization(beanFactory); // 完成刷新,包括發布容器刷新事件 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } /// 銷毀所有已經創建好的bean,以防止內存浪費 destroyBeans(); // 重置活動標志 cancelRefresh(ex); throw ex; } finally { // 重置反射緩存 resetCommonCaches(); } } }

refresh方法的設計使用了模板方法設計模式,它設定了容器刷新的流程,并把特定階段的執行延遲到子類中執行,比如bean工廠的創建。它還在特定的階段提供鉤子方法,以方便子類根據自身需要進一步完成更多的操作。下面我們一步一步的探討refresh方法的執行流程。下圖是它的一個大概流程圖。

refresh方法在容器的基本配置完成后被調用,它是spring容器初始化過程的主要戰場,下面我們一步一步的探討refresh方法的執行流程。

容器刷新過程


1. 容器刷新前準備

在refresh方法的第1步中,調用AbstractApplicationContext的prepareRefresh()方法完成容器刷新前的準備,代碼如下。

protected void prepareRefresh() { // 設置啟動時間 this.startupDate = System.currentTimeMillis(); this.closed.set(false); // 把容器設置為活動 this.active.set(true); if (logger.isInfoEnabled()) { logger.info("Refreshing " + this); } // 鉤子方法,讓子類把所有的stub屬性資源替換成真正需要的屬性資源。 initPropertySources(); // 驗證所有被標注為required的屬性是否可被解析 getEnvironment().validateRequiredProperties(); // 允許事件傳播器可用的時候發布一些事件 // earlyApplicationEvents存儲需要在事件傳播器可用時發布的事件 this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>(); }

prepareRefresh方法設置容器啟動時間和活動標志,以及通過調用initPropertySources()方法完成所有的property資源的初始化。initPropertySources()方法是一個空實現,子類可以用它來完成property資源的初始化。例如,下面代碼是在AbstractRefreshableWebApplicationContext類中的實現

@Override protected void initPropertySources() { super.initPropertySources(); ConfigurableEnvironment env = this.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment)env).initPropertySources( this.servletContext, this.servletConfig); } }

這個方法主要是把ServletContext和ServletConfig對象保存到ConfigurableWebEnvironment環境對象中,以方便環境對象通過getProperty(String key)方法獲取定義在ServletContext和ServletConfig中特定的初始化init-param參數。

2. 創建BeanFactory

執行AbstractApplicationContext的obtainFreshBeanFactory方法,獲取最新的bean工廠對象,代碼如下。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { // 刷新bean工廠,是一個抽象方法,由子類實現。 refreshBeanFactory(); // 從子類中獲取bean工廠,也是一個抽象方法,由子類實現 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }

obtainFreshBeanFactory方法首先調用子類的refreshBeanFactory()方法刷新bean工廠,然后調用子類的getBeanFactory()方法獲取bean工廠。在spring中,refreshBeanFactory()在GenericApplicationContext類和AbstractRefreshableApplicationContext類中都有實現,下面是在AbstractRefreshableApplicationContext類中的實現。

@Override protected final void refreshBeanFactory() throws BeansException { if (hasBeanFactory()) { // 如果當前上線文容器已有bean工廠 // 銷毀bean工廠中所有單例bean destroyBeans(); // 關閉已有的bean工廠 closeBeanFactory(); } try { // 創建一個新的bean工廠 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 自定義bean工廠,包括設置是否允許覆蓋相同ID的bean,是否允許循環引用,等等 customizeBeanFactory(beanFactory); // 加載所有BeanDefinition,是一個抽象方法,有子類實現 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }

這個方法里面,首先把已創建的單例bean銷毀并關閉持有的bean工廠,然后調用createBeanFactory()方法重新創建一個x新的bean工廠代碼如下。最后,并調用子類的loadBeanDefinitions方法把BeanDefinition對象加載到bean工廠中。

/** * 創建一個新的bean工廠 **/ protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }

3. 初始化BeanFactory

獲取到BeanFactory對象后,refresh()方法調用AbstractApplicationContext對象的prepareBeanFactory方法和postProcessBeanFactory方法完成bean工廠的初始化。在這個階段,容器中所有的BeanDefinition對象已經被注冊到bean工廠中(除被@Configuration注解的類管理的bean配置外),但是沒有任何一個BeanDefinition所代表的bean被創建,包括工廠后處理器。下面我們看看這個兩個方法的執行情況。

首先,調用prepareBeanFactory方法。這個方法主要功能是,為bean工廠設置容器的類加載器,以及一些特定的bean后處理器,代碼如下。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 要求bean工廠和容器共用同一個類加載器 beanFactory.setBeanClassLoader(getClassLoader()); // 設置SpEL表達式解析器 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver()); // 添加Resource編輯器注冊器 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 添加ApplicationContextAwareProcessor后處理器 // 有可能某些工廠后處理器實現了ApplicationContextAware、ResourceLoaderAware等等如下類似接口 // ApplicationContextAwareProcessor后處理器就就為這些接口傳遞相應的對象 // 因此,在執行工廠后處理器前,必須要設置此后處理器 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); // Detect a LoadTimeWeaver and prepare for weaving, if found. // 檢測用戶是否配置了loadTimeWeaver bean對象 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { // 添加LoadTimeWeaverAwareProcessor后處理器,此后處理器用于向bean中注入LoadTimeWeaver對象 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // 為類型匹配檢測配置臨時的類加載器 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // 注冊默認的環境bean對象 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } // 注冊OS系統屬性對象 if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } // 注冊OS系統環境對象 if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }

然后,調用postProcessBeanFactory方法。這個方法在AbstractApplicationContext類中的定義如下。

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { }

postProcessBeanFactory方法被作為鉤子方法,讓子類在bean工廠初始化的時候根據自身需要,對bean工廠做更多的操作。在web應用中,AbstractRefreshableWebApplicationContext類重寫此方法,代碼如下。

/** * 注冊request/session作用域, 和ServletContextAwareProcessor bean后處理器, . */ @Override protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 添加ServletContextAwareProcessor后處理器 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); // 注冊request/session作用域 WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); // 把ServletContext對象和ServletConfig對象等以單例bean的形式注冊到bean工廠中 WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); }

4. 執行bean工廠后處理器的postProcessBeanFactory方法

bean工廠初始化完成后,refresh()方法調用AbstractApplicationContext的invokeBeanFactoryPostProcessors方法完成容器中所有bean工廠后處理器的執行,代碼如下。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 把執行工廠后處理器的任務委托給PostProcessorRegistrationDelegate PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // 檢測LoadTimeWeaver對象 // 聲明:String LOAD_TIME_WEAVER_BEAN_NAME = "loadTimeWeaver"; if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }

這段代碼主要是把工廠后處理器的任務委托給PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法,此方法的代碼如下。

public static void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // 首先執行BeanDefinitionRegistryPostProcessors Set<String> processedBeans = new HashSet<String>(); if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>(); List<BeanDefinitionRegistryPostProcessor> registryPostProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); // 遍歷容器中的工廠后處理器,并執行BeanDefinitionRegistryPostProcessors for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { BeanDefinitionRegistryPostProcessor registryPostProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor; // 執行BeanDefinitionRegistryPostProcessors的 // ->postProcessBeanDefinitionRegistry方法 registryPostProcessor.postProcessBeanDefinitionRegistry(registry); registryPostProcessors.add(registryPostProcessor); } else { regularPostProcessors.add(postProcessor); } } // 獲取bean工廠中定義的BeanDefinitionRegistryPostProcessor對象 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); // 首先,執行實現了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor對象 List<BeanDefinitionRegistryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>(); for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); processedBeans.add(ppName); } } sortPostProcessors(beanFactory, priorityOrderedPostProcessors); registryPostProcessors.addAll(priorityOrderedPostProcessors); invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry); // 然后,執行實現了Ordered接口的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); } } sortPostProcessors(beanFactory, 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; } } } // 執行BeanDefinitionRegistryPostProcessor工廠后處理器 invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory); // 執行容器中普通的工廠后處理器 invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } else { // 執行容器中的bean工廠后處理器 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); } // 獲取定義在bean工廠中的bean工廠后處理器 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); // 把bean工廠后處理器按PriorityOrdered、Ordered和其他來分類 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)) { // 排除前面已經執行了的后處理器 } 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); } } // 首先執行實現了PriorityOrdered接口的后處理器 sortPostProcessors(beanFactory, priorityOrderedPostProcessors); invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); // 然后執行實現了Ordered接口的后處理器 List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : orderedPostProcessorNames) { orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } sortPostProcessors(beanFactory, orderedPostProcessors); invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); // 最后執行其他的后處理器 List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>(); for (String postProcessorName : nonOrderedPostProcessorNames) { nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); } invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); // 清除工廠中的元數據緩存 beanFactory.clearMetadataCache(); } /** * 執行給定的BeanDefinitionRegistryPostProcessor beans. */ private static void invokeBeanDefinitionRegistryPostProcessors( Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanDefinitionRegistry(registry); } } /** * 執行給定的bean工廠 **/ private static void invokeBeanFactoryPostProcessors( Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) { for (BeanFactoryPostProcessor postProcessor : postProcessors) { postProcessor.postProcessBeanFactory(beanFactory); } }

上面的執行流程用圖表達如下。 這里寫圖片描述

上圖很明顯的表達了bean工廠后處理器的執行順序,但這里還有兩點需要說明的。

a. 為什么要先執行BeanDefinitionRegistryPostProcessor?因為實現BeanDefinitionRegistryPostProcessor 接口的后處理器可以在bean工廠創建其他bean之前添加更多的BeanDefinition對象到bean工廠中去。比如spring中ConfigurationClassPostProcessor類就是這樣一種工廠后處理器,它主要把被@Configuration注解的類中定義的bean信息轉換成BeanDefinition對象,并注冊到bean工廠中。

b. 這個流程中有一個很明顯的規定就是,不管是什么工廠后處理器,都必須先執行容器中的工廠后處理器后,才執行bean工廠中的工廠后處理器。

5. 注冊BeanPostProcessor

refresh()方法執行完bean工廠后處理器后,接著調用AbstractApplicationContext的registerBeanPostProcessors方法向bean工廠注冊bean后處理器,registerBeanPostProcessors方法的代碼如下。

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) { // 把注冊bean后處理器的任務委托給PostProcessorRegistrationDelegate PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this); }

registerBeanPostProcessors方法把注冊bean后處理器的任務委托給PostProcessorRegistrationDelegate類的registerBeanPostProcessors方法,下面是這個方法的代碼。

public static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { // 從bean工廠中找到所有BeanPostProcessor對象的名稱 String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); // 注冊BeanPostProcessorChecker后處理器 int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length; beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount)); // 對所有的bean后處理器根據實現PriorityOrdered,Ordered和其他的進行分組 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); } } // 首先注冊實現了PriorityOrdered接口的bean后處理器 sortPostProcessors(beanFactory, priorityOrderedPostProcessors); registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); // 然后注冊實現了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); } } sortPostProcessors(beanFactory, orderedPostProcessors); registerBeanPostProcessors(beanFactory, orderedPostProcessors); // 再次,注冊所有普通的后處理器 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); // 最后,重新注冊所有內部后處理器 // ->即實現了MergedBeanDefinitionPostProcessor接口的后處理器 sortPostProcessors(beanFactory, internalPostProcessors); registerBeanPostProcessors(beanFactory, internalPostProcessors); beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); } /** * 注冊指定的BeanPostProcessor beans. */ private static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) { for (BeanPostProcessor postProcessor : postProcessors) { beanFactory.addBeanPostProcessor(postProcessor); } }

這部分代碼注冊bean后處理器的注冊流程如下。

這里寫圖片描述

整個流程根據PriorityOrdered、Ordered、非Ordered的順序注冊bean后處理器,最后注冊MergedBeanDefinitionPostProcessor bean后處理器。其中MergedBeanDefinitionPostProcessor會在其他bean后處理器執行前執行它的postProcessMergedBeanDefinition方法。

6. 初始化MessageSource國際化消息

執行AbstractApplicationContext的initMessageSource方法,代碼如下

protected void initMessageSource() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 聲明:public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource"; // 檢測用戶是否指定了messageSource if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) { this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class); // 使當前messageSource能夠使用父容器中的messageSource if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) { HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource; if (hms.getParentMessageSource() == null) { hms.setParentMessageSource(getInternalParentMessageSource()); } } if (logger.isDebugEnabled()) { logger.debug("Using MessageSource [" + this.messageSource + "]"); } } else { // 用戶沒有指定messageSource // 使用一個空的MessageSource,以能夠接受getMessage方法的調用 DelegatingMessageSource dms = new DelegatingMessageSource(); dms.setParentMessageSource(getInternalParentMessageSource()); this.messageSource = dms; beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource); if (logger.isDebugEnabled()) { logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME + "': using default [" + this.messageSource + "]"); } } }

注意:如果要使用國際化消息,必須提供bean名稱為messageSource的MessageSource對象,形如下面的配置。

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basenames"> <list> <value>/WEB-INF/languages/globe/messages</value> </list> </property> <property name="cacheSeconds" value="1800"/> <property name="defaultEncoding" value="UTF-8"/> </bean>

7. 初始化事件傳播器

refresh()方法完成國際化消息對象初始化后,接著調用AbstractApplicationContext的initApplicationEventMulticaster方法為容器添加事件傳播器,代碼如下。

protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 聲明:public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster"; // 檢測用戶是否制定了事件傳播器 if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); if (logger.isDebugEnabled()) { logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]"); } } else { // 使用默認的事件傳播器 this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); if (logger.isDebugEnabled()) { logger.debug("Unable to locate ApplicationEventMulticaster with name '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "': using default [" + this.applicationEventMulticaster + "]"); } } }

8. 其他初始化

refresh()方法完成國際化消息和事件傳播器的初始化后,把容器的初始化交給onRefresh()方法,代碼如下。

protected void onRefresh() throws BeansException { // For subclasses: do nothing by default. }

onRefresh()方法被設計成容器初始化的鉤子,以方便子類初始化其他特定的bean。例如,下面是在AbstractRefreshableWebApplicationContext類中onRefresh()方法被重寫的代碼。

/** * Initialize the theme capability. */ @Override protected void onRefresh() { this.themeSource = UiApplicationContextUtils.initThemeSource(this); }

其中,UiApplicationContextUtils工具類的initThemeSource(ApplicationContext context)方法的代碼如下。

public static ThemeSource initThemeSource(ApplicationContext context) { // 聲明有:public static final String THEME_SOURCE_BEAN_NAME = "themeSource"; if (context.containsLocalBean(THEME_SOURCE_BEAN_NAME)) { ThemeSource themeSource = context.getBean(THEME_SOURCE_BEAN_NAME, ThemeSource.class); // 使themeSource關聯父容器,這個父容器必須實現了ThemeSource接口 if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) { HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource; if (hts.getParentThemeSource() == null) { hts.setParentThemeSource((ThemeSource) context.getParent()); } } if (logger.isDebugEnabled()) { logger.debug("Using ThemeSource [" + themeSource + "]"); } return themeSource; } else { HierarchicalThemeSource themeSource = null; if (context.getParent() instanceof ThemeSource) { // 把對ThemeSource的操作代理給父容器 themeSource = new DelegatingThemeSource(); themeSource.setParentThemeSource((ThemeSource) context.getParent()); } else { // 使用默認的ThemeSource themeSource = new ResourceBundleThemeSource(); } if (logger.isDebugEnabled()) { logger.debug("Unable to locate ThemeSource with name '" + THEME_SOURCE_BEAN_NAME + "': using default [" + themeSource + "]"); } return themeSource; } }

9. 注冊監聽器

執行完成子類實現的onRefresh()方法,需要向容器中注冊各種監聽器,此時執行AbstractApplicationContext的registerListeners()方法,這個方法的代碼如下。

protected void registerListeners() { // 首先注冊容器中特定的事件監聽器 for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // 找到用戶配置的所有的監聽器bean名稱 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { // 在事件傳播器中只保存監聽器的bean名稱 // 這里不實例化監聽器的原因是為了讓后處理器在它們真正實例化的時候作用于它們 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // 發布那些需要提前發布的事件 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }

10. 實例化非延遲單例bean

前面所有的初始化操作都完成了后,則開始實例化剩下的單例非延遲加載的bean。通過執行AbstractApplicationContext的finishBeanFactoryInitialization方法完成,這個方法的代碼如下。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 初始化ConversionService // 在ConfigurableApplicationContext接口中聲明:String CONVERSION_SERVICE_BEAN_NAME = "conversionService"; if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // 注冊一個默認的內部value解析器 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(new StringValueResolver() { @Override public String resolveStringValue(String strVal) { return getEnvironment().resolvePlaceholders(strVal); } }); } // 初始化LoadTimeWeaverAware對象來支持注冊他們的transformers String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // 停止使用臨時類加載器來做類型匹配 beanFactory.setTempClassLoader(null); // 允許緩存所有的bean元數據定義,不希望今后再更改 beanFactory.freezeConfiguration(); // 初始化所有非延遲單例bean beanFactory.preInstantiateSingletons(); }

11. 完成刷新

refresh()方法的最后一步,AbstractApplicationContext的finishRefresh方法,完成容器刷新,執行LifecycleProcessor對象的onRefresh方法,以及發布刷新事件。代碼如下,

protected void finishRefresh() { // 初始化生命周期處理器,默認為DefaultLifecycleProcessor initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. // 首先把刷新操作傳遞給生命周期處理器 getLifecycleProcessor().onRefresh(); // 最后發布容器刷新事件 publishEvent(new ContextRefreshedEvent(this)); // 把spring容器加入到LiveBeansView的MBeanServer中 LiveBeansView.registerApplicationContext(this); } /** * 初始化生命周期處理器 **/ protected void initLifecycleProcessor() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 聲明:public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor"; if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) { // 使用用戶指定的生命周期處理器 this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class); if (logger.isDebugEnabled()) { logger.debug("Using LifecycleProcessor [" + this.lifecycleProcessor + "]"); } } else { // 使用默認的聲明周期處理器 DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor(); defaultProcessor.setBeanFactory(beanFactory); this.lifecycleProcessor = defaultProcessor; beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor); if (logger.isDebugEnabled()) { logger.debug("Unable to locate LifecycleProcessor with name '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "': using default [" + this.lifecycleProcessor + "]"); } } }

到這里spring的刷新也就完成了。

總結


(1)spring的所有容器都直接或間接繼承了抽象類AbstractApplicationContext。

(2) spring的容器在創建并完成基本的配置后,在初次使用前,還必須執行refresh()方法。

(3)實現BeanDefinitionRegistryPostProcessor 接口的后處理器可以在bean工廠創建其他bean之前添加更多的BeanDefinition對象到bean工廠中去。比如spring中ConfigurationClassPostProcessor類,它主要把被@Configuration注解的類中定義的bean信息轉換成BeanDefinition對象,并注冊到bean工廠中。

(4)可以自定義BeanPostProcessor工廠后處理器對BeanDefinition對象做處理,比如spring的PreferencesPlaceholderConfigurer工廠后處理器,它把屬性文件中的值與BeanDefinition中相應的屬性值相替換。

(5)指定國際化消息時,MessageSource對象的bean名稱必須為messageSource。

(6)容器刷新過程中的鉤子方法有: a. initPropertySources()由子類根據自身的應用環境初始化property資源。 b. postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)用于在bean工廠后處理器執行前由子類對bean工廠做更多的初始化操作。 c. onRefresh()用于初始化子類中特定的bean。

(7)LiveBeansView的使用

Spring容器初始化過程中的最后一步,把spring容器加入到LiveBeansView的MBeanServer中。這個LiveBeansView它是一個MBean對象,它的作用是查看當前活動的bean以及這些bean的依賴。下面步驟介紹如何使用它。

a. 在web.xml文件配置如下,其中param-value可以任意取

<context-param> <param-name>spring.liveBeansView.mbeanDomain</param-name> <param-value>chyohn_liveBeansView</param-value> </context-param>

b. 啟動應用后,打開%java_HOME%/bin/jconsole.exe程序,如下

這里寫圖片描述

c. 我使用的tomcat服務器啟動的,點擊第2個鏈接,進入的頁面,如下

這里寫圖片描述

上面的JSON數據中就包含當前spring容器中所有的bean,是不是很神奇?這也是java MBean的一個例子。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 国产91丝袜在线播放 | 欧美日韩高清一区 | 成年片在线观看 | 色播视频在线播放 | 欧美精品久久久久久久多人混战 | 国产剧情v888av | 久久人 | 日韩精品免费一区二区三区 | 在线免费观看麻豆 | 免费久久久 | 国产精品毛片无码 | 日本成人在线免费 | 亚洲二区不卡 | 高潮激情aaaaa免费看 | 国产精品视频专区 | 老子午夜影院 | 国产精品免费久久久久 | 国产羞羞视频在线观看免费应用 | 日日狠狠久久偷偷四色综合免费 | 日韩做爰视频免费 | 欧美一级黄色免费 | 久久亚洲春色中文字幕久久 | 免费h片网站 | 欧美精品一区二区久久久 | 午夜视频久久久 | 国产亚洲精品久久久久久久久久 | av免费不卡国产观看 | 精品国产成人 | 亚洲小视频在线观看,com | 久久55| 草操视频 | 精品一区久久久 | 91福利影视 | 成人一区视频 | 中文国产在线视频 | 久久精品视频黄色 | 91社影院在线观看 | 亚洲3atv精品一区二区三区 | 午夜视频在线免费观看 | 蜜桃网在线观看 | 沉沦的校花奴性郑依婷c到失禁 |