接上文Spring 學習記錄7 初識XmlWebApplicationContexthtml
refresh方法是定義在父類AbstractApplicationContext中的.它內部會調用不少方法.有一些是在子類中實現的.算是模板方法的設計模式吧.主要做用就是初始化wac加載各類bean等做用.web
1 @Override 2 public void refresh() throws BeansException, IllegalStateException { 3 synchronized (this.startupShutdownMonitor) { 4 // Prepare this context for refreshing. 5 // 記錄開始wac開始初始化的時間,設置激活標記,servlet的相關param設置到env(以前作過1次),校驗env中必須的props 6 prepareRefresh(); 7 8 // Tell the subclass to refresh the internal bean factory. 9 // 刷新初始化BF並獲取它,將舊的BF裏的bean刪掉,新建1個BF,加載XML配置文件 10 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 11 12 // Prepare the bean factory for use in this context. 13 prepareBeanFactory(beanFactory); 14 15 try { 16 // Allows post-processing of the bean factory in context subclasses. 17 postProcessBeanFactory(beanFactory); 18 19 // Invoke factory processors registered as beans in the context. 20 invokeBeanFactoryPostProcessors(beanFactory); 21 22 // Register bean processors that intercept bean creation. 23 registerBeanPostProcessors(beanFactory); 24 25 // Initialize message source for this context. 26 initMessageSource(); 27 28 // Initialize event multicaster for this context. 29 initApplicationEventMulticaster(); 30 31 // Initialize other special beans in specific context subclasses. 32 onRefresh(); 33 34 // Check for listener beans and register them. 35 registerListeners(); 36 37 // Instantiate all remaining (non-lazy-init) singletons. 38 finishBeanFactoryInitialization(beanFactory); 39 40 // Last step: publish corresponding event. 41 finishRefresh(); 42 } catch (BeansException ex) { 43 logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex); 44 45 // Destroy already created singletons to avoid dangling resources. 46 destroyBeans(); 47 48 // Reset 'active' flag. 49 cancelRefresh(ex); 50 51 // Propagate exception to caller. 52 throw ex; 53 } 54 } 55 }
第一個被調用的方法就是它設計模式
主要做用:session
記錄開始wac開始初始化的時間,設置激活標記,servlet的相關param設置到env(以前作過1次),校驗env中必須的propsapp
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 * 記錄開始wac開始初始化的時間,設置激活標記,servlet的相關param設置到env(以前作過1次),校驗env中必須的props 5 */ 6 protected void prepareRefresh() { 7 this.startupDate = System.currentTimeMillis(); 8 this.active.set(true); 9 10 if (logger.isInfoEnabled()) { 11 logger.info("Refreshing " + this); 12 } 13 14 // Initialize any placeholder property sources in the context environment 15 // 講servlet的config和context裏的params賦值給env..以前已經作過一次了,這個wac可能會由servlet初始化,這樣的話ServletConfig就不會爲空 16 initPropertySources(); 17 18 // Validate that all properties marked as required are resolvable 19 // see ConfigurablePropertyResolver#setRequiredProperties 20 // 在env中有一些properties是必須的,校驗這些props.沒有就拋出異常 21 getEnvironment().validateRequiredProperties(); 22 }
L16..這個方法作了什麼直接看註釋吧..ide
1 /** 2 * {@inheritDoc} 3 * <p>Replace {@code Servlet}-related property sources. 4 */ 5 @Override 6 protected void initPropertySources() { 7 ConfigurableEnvironment env = getEnvironment(); 8 if (env instanceof ConfigurableWebEnvironment) { 9 ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, this.servletConfig); 10 } 11 }
就是拿servletContext和servletConfig去填充env....和以前作的同樣....若是是listener初始化的話這裏servletConfig確定是空的.函數
L21 對env裏的必須的屬性進行校驗.若是這些屬性不存在的話就報錯.(可是我源碼裏搜索了一下並無找到調用設置必須屬性的地方...不知道怎麼使用才能標記屬性爲必須....)post
主要做用:學習
刷新初始化BF並獲取它,將舊的BF裏的bean刪掉,新建1個BF,加載XML配置文件ui
1 /** 2 * Tell the subclass to refresh the internal bean factory. 3 * 刷新初始化BF並獲取它,將舊的BF裏的bean刪掉,新建1個BF,加載XML配置文件 4 * 5 * @return the fresh BeanFactory instance 6 * @see #refreshBeanFactory() 7 * @see #getBeanFactory() 8 */ 9 protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { 10 refreshBeanFactory(); // 刷新BF 11 ConfigurableListableBeanFactory beanFactory = getBeanFactory(); 12 if (logger.isDebugEnabled()) { 13 logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); 14 } 15 return beanFactory; 16 }
L10 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(); // 刪除全部單例bean 10 closeBeanFactory(); // wac中的BF成員域=null. 11 } 12 try { 13 DefaultListableBeanFactory beanFactory = createBeanFactory(); // 建立1個新的DefaultListableBeanFactory 14 beanFactory.setSerializationId(getId()); // 設置ID 15 customizeBeanFactory(beanFactory); // wac 中的屬性 allowBeanDefinitionOverriding allowCircularReferences 覆蓋BF 16 loadBeanDefinitions(beanFactory); // 加載BeanDefinitions. 17 synchronized (this.beanFactoryMonitor) { 18 this.beanFactory = beanFactory; 19 } 20 } catch (IOException ex) { 21 throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); 22 } 23 }
主要做用就是先把以前的beanfactory裏建立的bean都銷燬,而後銷燬beanfactory.
而後新建1個DefaultListableBeanFactory,並配置一些經過wac配置的屬性.
再加載一下bean的配置.在這裏由於wac是XmlWebApplicationContext,因此bean的配置確定是寫在XML裏的了.
最後把bf對象設置到wac的成員域上.
L11獲得以前設置的新的BF並在L15返回...
主要做用:
1.設置BF解析bean配置須要用到的一些對象好比env. 2.註冊一些BeanPostProcessor好比ApplicationContextAwareProcessor去設置Aware須要的對象 3.忽略一些特定class注入的對象,設置一些特定class注入的對象爲指定值 4.將一些env中的properties map當作bean註冊到BF中
1 /** 2 * Configure the factory's standard context characteristics, 3 * such as the context's ClassLoader and post-processors. 4 * 5 * @param beanFactory the BeanFactory to configure 6 */ 7 protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { 8 // Tell the internal bean factory to use the context's class loader etc. 9 // BF須要解析屬性或者轉化須要用到env和其餘相關的類.從wac中設置進去 10 beanFactory.setBeanClassLoader(getClassLoader()); 11 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); 12 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); 13 14 // Configure the bean factory with context callbacks. 15 // 由於bean是在BF中建立的,因此若是他們須要用到wac的callback好比ApplicationEventPublisherAware的方法或者ApplicationContextAware, 16 // 那就須要再BF生成bean的時候注入applicationcontext或者它的相關類.好比env 17 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); 18 beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); 19 beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); 20 beanFactory.ignoreDependencyInterface(MessageSourceAware.class); 21 beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); 22 beanFactory.ignoreDependencyInterface(EnvironmentAware.class); 23 24 // BeanFactory interface not registered as resolvable type in a plain factory. 25 // MessageSource registered (and found for autowiring) as a bean. 26 // 若是要注入如下類型的bean,直接使用這些對象 27 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); 28 beanFactory.registerResolvableDependency(ResourceLoader.class, this); 29 beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); 30 beanFactory.registerResolvableDependency(ApplicationContext.class, this); 31 32 // Detect a LoadTimeWeaver and prepare for weaving, if found. 33 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { 34 beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); 35 // Set a temporary ClassLoader for type matching. 36 beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); 37 } 38 39 // Register default environment beans. 40 // 將一些properties當作bean放到BF中 41 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { 42 beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); 43 } 44 if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { 45 beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); 46 } 47 if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { 48 beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); 49 } 50 }
第一個代碼塊就是設置一些BF解析bean須要用到的對象.好比env.
第二個代碼塊就是add了一些XXXAwareProcess.好比applicationContextAware...BF在建立這個bean之後會調用ApplicationContextAwareProcessor的回調函數去注入applicationContext.
而後忽略了一些接口,他們不會被注入實現類.
第三個代碼塊配置了一些接口的注入的實現類.
第四個代碼又注入了一個BeanPostProcessor,這個彷佛和AOP有關係.沒研究過.
第五個代碼塊就是把env中的一些props當作bean註冊到BF中去.
又是1個模板方法.能夠對BF進行一些加工定製.
在web環境下有重寫過.
主要做用:
1.設置一個BeanPostProcess爲ServletContextAware的實現類注入servlet相關對象
2.在BF中增長requetsScope等Scope
3.把servletContext,Config,ServletInitParams,ServletAttribute當作Bean註冊到BF中
1 /** 2 * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc. 3 * 1.設置一個BeanPostProcess爲ServletContextAware的實現類注入servlet相關對象 4 * 2.在BF中增長requetsScope等Scope 5 * 3.把servletContext,Config,ServletInitParams,ServletAttribute當作Bean註冊到BF中 6 * 7 */ 8 @Override 9 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { 10 // 設置一個BeanPostProcess爲ServletContextAware的實現類注入servlet相關對象 11 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); 12 beanFactory.ignoreDependencyInterface(ServletContextAware.class); 13 beanFactory.ignoreDependencyInterface(ServletConfigAware.class); 14 15 // 在BF中增長requetsScope等Scope 16 WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); 17 // 把servletContext,Config,ServletInitParams,ServletAttribute當作Bean註冊到BF中 18 WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); 19 }
初始化並調用配置的BeanFactoryPostProcessor..具體比較複雜.等後續更多學習之後再分享.
基本同invokeBeanFactoryPostProcessors方法,這是這裏不會調用BeanPostProcess只是向BF裏註冊而已.具體比較複雜.等後續更多學習之後再分享.