SpringBoot启动流程之(refreshContext)
- 流程图:
- 前面讲了Spring对于Context的基本处理
- 这里补一下Context的基本类型的建立
- 通过webApplicationType来加载不同的应用基本Context路径,最终通过反射来进行构建Context
- 我们这里所使用的便是AnnotationConfigServletWebServerApplicationContext.class
- AnnotationConfigServletWebServerApplicationContext的结构体
- 来自其父类的Refresh:
- refresh调用堆栈:
protected ConfigurableApplicationContext createApplicationContext(){ Class<?> contextClass=this.applicationContextClass; if(contextClass==null){ //根据当前应用类型加载基本Context环境 try{ switch(this.webApplicationType){ case SERVLET: //我们是传统的Servlet应用,这里通过SPI加载了org.springframework.boot." //"web.servlet.context路劲下的AnnotationConfigServletWebServerApplicationContext类 contextClass=Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; //······删除了......
AbstractApplicationContext#refresh()
- 这是一个模板方法,定义了一系列了的操作顺序集合
@Override public void refresh()throws BeansException,IllegalStateException{ synchronized (this.startupShutdownMonitor){ //准备上下文环境 prepareRefresh(); //建立beanFactory,加载了bean的定义,进行resources(xml,properties......)解析 ConfigurableListableBeanFactory beanFactory=obtainFreshBeanFactory(); //为beanFactory进行了各种填充 prepareBeanFactory(beanFactory); try{ //为beanFactory添加后置处理器,并且对Web应用程序(session......) //的各种生命域进行了注册,允许context子类对beanFactory进行后处理 postProcessBeanFactory(beanFactory); //在context中注册、调用了beanFactory的后置处理器,并且对@Configration,@Bean......注解进行了处理,这里主要对bean的定义信息的配置 invokeBeanFactoryPostProcessors(beanFactory); //注册实例化bean的拦截器 registerBeanPostProcessors(beanFactory); //初始化ConfigurableListableBeanFactory的MessageSources initMessageSource(); //初始化ApplicationEventMulticaster initApplicationEventMulticaster(); // 初始化Tomcat容器,并且启动 onRefresh(); //listeners的注册,以及广播的发布 registerListeners(); // 初始化非惰性单例bean finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch(BeansException ex){ // 清理已经创建的单例资源 destroyBeans(); // 重置激活状态 cancelRefresh(ex); // Propagate exception to caller. throw ex; } finally{ //重置Spring的常见反射元数据缓存 resetCommonCaches(); } } }
prepareRefresh();
• 初始化应用环境environment的Context以及Config • 对listeners,event初始化 protected void prepareRefresh(){ // 激活容器. this.startupDate=System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if(logger.isDebugEnabled()){ if(logger.isTraceEnabled()){ logger.trace("Refreshing "+this); } else{ logger.debug("Refreshing "+getDisplayName()); } } //采用实际实例替换掉environment的Context以及Config,为当前无法操作,但是以后存在操作的预留的占位符 initPropertySources(); //验证Environment指定的属性不能为空 getEnvironment().validateRequiredProperties(); //为所有liteners初始化 if(this.earlyApplicationListeners==null){ this.earlyApplicationListeners=new LinkedHashSet<>(this.applicationListeners); } else{ //重置所有Listeners this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } //初始化事件,保证广播一经创建,则发布所有事件 this.earlyApplicationEvents=new LinkedHashSet<>(); }
prepareRefresh->initPropertySources
- initPropertySources细节
- 调用堆栈
- 可以看出最终委托给了WebApplicationContextUtils#initServletPropertySources
- 代码截图
- 可以看出,该方法主要做的事就是初始化Environment的ServletContext以及ServletConfig
obtainFreshBeanFactory();
• obtainFreshBeanFactory代码体 • 建立了BeanFactory,并且对xml文件进行了读取,解释 protected ConfigurableListableBeanFactory obtainFreshBeanFactory(){ //看后面 refreshBeanFactory(); return getBeanFactory(); }
obtainFreshBeanFactory#refreshBeanFactory
protected final void refreshBeanFactory()throws BeansException{ //当前是否存在bean工厂 if(hasBeanFactory()){ //如果存在则销毁这个工厂存在的所有单例bean destroyBeans(); //然后初始化bean的id,置当前context的BeanFactory为空 closeBeanFactory(); } try{ //默认创建DefaultListableBeanFactory工厂,并将此上下文父级的内部 bean工厂作为父bean工厂 DefaultListableBeanFactory beanFactory=createBeanFactory(); //为beanFactory设置序列化id beanFactory.setSerializationId(getId()); //自定义beanFactory设置,是否允许覆盖同一key的bean;是否允许循环引用 customizeBeanFactory(beanFactory); //加载定义bean的详细信息 loadBeanDefinitions(beanFactory); this.beanFactory=beanFactory; } catch(IOException ex){ throw new ApplicationContextException("I/O error parsing bean definition source for "+getDisplayName(),ex); } }
refreshBeanFactory->createBeanFactory
- 销毁原来存在的beanFactory,为context创建一个级联beanFactory
protected DefaultListableBeanFactory createBeanFactory(){ //默认此context创建一个DefaultListableBeanFactory. return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }; protected BeanFactory getInternalParentBeanFactory(){ //如果实现了ConfigurableApplicationContext,则返回父上下文的内部bean工厂;否则,返回父上下文本身. return(getParent()instanceof ConfigurableApplicationContext? ((ConfigurableApplicationContext)getParent()).getBeanFactory():getParent()); }
refreshBeanFactory->loadBeanDefinitions
- loadBeanDefinitions抽象方法:
- 该接口定义了bean定义的规范方式,将bean定义加载到给定的bean工厂,通常通过委托给一个或多个BeanDefinitionReader实现
- BeanDefinitionReader接口:
- 这个接口实际上给出了对于bean定义读取的规范,主要包括以下几个方面
- 怎么统一处理bean的定义,并且与bean工厂建立联系?
- 加载bean资源的加载器从哪来?
- bean定义的资源从哪里来?
- bean的格式化转换怎么处理?
//bean定义阅读器的规范接口,但是不需要强制实现 public interface BeanDefinitionReader { /** * 返回bean工厂以注册bean定义. * 工厂通过BeanDefinitionRegistry接口暴露, * 封装了与bean定义处理相关的方法 */ BeanDefinitionRegistry getRegistry(); /** * 获取资源加载器,以用于加载bean资源 */ @Nullable ResourceLoader getResourceLoader(); /** * 获取bean的classLoader */ @Nullable ClassLoader getBeanClassLoader(); /** * 获取bean名字规范定义的加载器 */ BeanNameGenerator getBeanNameGenerator(); /** * 从指定Resource加载bean的定义. */ int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException; /** * 从多个Resource加载bean的定义. */ int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException; /** * 从指定位置资源加载bean的定义 */ int loadBeanDefinitions(String location) throws BeanDefinitionStoreException; /** * 从多个指定位置资源加载bean的定义 */ int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException; }
prepareBeanFactory(beanFactory)
- 为obtainFreshBeanFactory产生的BeanFactory进一步完善,配置BeanFactory基于context的特征,其中主要定义了如下:
- 指定了内部BeanFactory使用context的classloader
- 使用上下文回调配置bean工厂(保留疑问,不知道干啥???)
- 将environment注册为bean
postProcessBeanFactory(beanFactory)
- 调用堆栈
ServletWebServerApplicationContext#postProcessBeanFactory
- 为beanFactory添加后置处理器
- 忽略某些自动装配的接口实现
- 为Web应用注册所需要的所必须的bean
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){ //添加后置处理器,并且转化为bean beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this)); //忽略ServletContextAware.class接口的自动装配 beanFactory.ignoreDependencyInterface(ServletContextAware.class); //BeanFactory注册web应用特有的局部作用域 registerWebApplicationScopes(); }
postProcessBeanFactory->registerWebApplicationScopes
private void registerWebApplicationScopes(){ //构建request,session作用域,默认为null ExistingWebApplicationScopes existingScopes=new ExistingWebApplicationScopes(getBeanFactory()); //初始化request= new RequestScope() ,session=new SessionScope(),并且刷新scope WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory()); //为BeanFactory注册局部作用域(scope) existingScopes.restore(); }
- registerWebApplicationScopes
- 代码段:
- 可以看出其主要做了这几件事
- 为应用注册了基础作用域
- 为应用注册了request,session等......对应的解析器