主题
接上文Spring 学习记录7 初识XmlWebApplicationContext
refresh方法
refresh方法是定义在父类AbstractApplicationContext中的.它内部会调用很多方法.有一些是在子类中实现的.算是模板方法的设计模式吧.主要作用就是初始化wac加载各种bean等作用.
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
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 }
prepareRefresh方法
第一个被调用的方法就是它
主要作用:
记录开始wac开始初始化的时间,设置激活标记,servlet的相关param设置到env(之前做过1次),校验env中必须的props
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..这个方法做了什么直接看注释吧..
1 /** 2 * {@inheritDoc} 3 *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里的必须的属性进行校验.如果这些属性不存在的话就报错.(但是我源码里搜索了一下并没有找到调用设置必须属性的地方...不知道怎么使用才能标记属性为必须....)
obtainFreshBeanFactory方法
主要作用:
刷新初始化BF并获取它,将旧的BF里的bean删掉,新建1个BF,加载XML配置文件
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();
![](http://img.e-com-net.com/image/info8/2b246dbcfe82488397e9aa432bbc4e31.gif)
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返回...
prepareBeanFactory方法
主要作用:
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中去.
postProcessBeanFactory方法
又是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 }
invokeBeanFactoryPostProcessors方法
初始化并调用配置的BeanFactoryPostProcessor..具体比较复杂.等后续更多学习以后再分享.
registerBeanPostProcessors方法
基本同invokeBeanFactoryPostProcessors方法,这是这里不会调用BeanPostProcess只是向BF里注册而已.具体比较复杂.等后续更多学习以后再分享.