【2】spring4.0.5初始化之listener

来源:互联网 发布:js删除对象中指定元素 编辑:程序博客网 时间:2024/05/30 23:29
springmvc的入口是web.xml配置的listener,也就是ContextLoaderListener 监听类。

ContextLoaderListener基于Web上下文级别的监听器在启动服务器时就创建ApplicationContext并且将配置的Spring Bean加载到XML中。

DispatcherServlet是一个请求分发控制器,所有匹配的URL都会通过该Servlet分发执行,在创建Servlet对象时会初始化Spring MVC相关配置。

        在web.xml中,我们看到基于ContextLoaderListener和DispatcherServlet都可以配置spring相关的XML,值得说明的是这两种方式加载spring的ApplicationContext上下文对象不是合并存储的,具体可参考http://blog.csdn.net/madun/article/details/8988860 所以个人建议,基于mvc相关的spring配置由DispatcherServlet加载,而其余的JavaBean都交给ContextLoaderListener加载


一、ContextLoaderListener

    1、解释       

     ContextLoaderListener是一个实现了ServletContextListener接口的监听器,在启动项目时会触发contextInitialized方法(该方法主要完成ApplicationContext对象的创建),在关闭项目时会触发contextDestroyed方法(该方法会执行ApplicationContext清理操作)。

    2、流程图

        

    3、代码流程

            【1】ContextLoaderListener.java    contextInitialized(ServletContextEvent event)

            【2】ContextLoader.java                  initWebApplicationContext(ServletContext servletContext)

            【3】ContextLoader.java                  createWebApplicationContext(ServletContext sc) 生成 
            【4】ContextLoader.java                  configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc)

XmlWebApplicationContext==》AbstractRefreshableApplicationContext ==》 AbstractApplicationContext 父类
 loadBeanDefinitions()方法                        refreshBeanFactory()方法实现类               refreshBeanFactory()抽象方法、 refresh()方法 
在ContextLoader类里面调用

    4、运行流程

①启动项目时触发contextInitialized方法,该方法就做一件事:通过父类contextLoaderinitWebApplicationContext方法创建Spring上下文对象。

②initWebApplicationContext方法做了三件事:创建WebApplicationContext;加载对应的Spring文件创建里面的Bean实例;将WebApplicationContext放入ServletContext(就是Java Web的全局变量)中。

③createWebApplicationContext创建上下文对象,支持用户自定义的上下文对象,但必须继承自ConfigurableWebApplicationContext,而             Spring MVC默认使用ConfigurableWebApplicationContext作为ApplicationContext(它仅仅是一个接口)的实现。

 这里用到强制转换ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;

④configureAndRefreshWebApplicationContext方法用于封装ApplicationContext数据并且初始化所有相关Bean对象。它会从web.xml中读取名为contextConfigLocation的配置,这就是spring xml数据源设置,然后放到ApplicationContext中,最后调用传说中的refresh()方法执行所有Java对象的创建

⑤完成ApplicationContext创建之后就是将其放入ServletContext中,注意它存储的key值常量。

      5、AbstractApplicationContext 父类的refresh()方法的里面步骤详解。

           ①、prepareRefresh();

                【1】设置刷新开始时间startupDate最后刷新完成toString()会log出来;

                【2】验证所有properties,StandardEnvironment extends AbstractEnvironment ;StandardEnvironment .                                    validateRequiredProperties()方法,调用父类的

                    通过StandardEnvironment .validateRequiredProperties();

                    //PropertySourcesPropertyResolver是配置文件处理工具类

               ConfigurablePropertyResolver propertyResolver  new PropertySourcesPropertyResolver(this.propertySources);

                    propertyResolver .validateRequiredProperties();//验证是否有空值

                        {  PropertySourcesPropertyResolver extends AbstractPropertyResolver

abstract class AbstractPropertyResolver implements ConfigurablePropertyResolver  }

            ②、obtainFreshBeanFactory();整个BeanFactory初始化的过程,定位资源由obtainFreshBeanFactory()来完成,//

         

      1、调用refreshBeanFactory();方法。调用父类的  refreshBeanFactory()//AbstractRefreshableApplicationContext类的方法

                            1.1 loadBeanDefinitions()方法  //调用自身的 loadBeanDefinitions()//XmlWebApplicationContext

                            1.2 loadBeanDefinitions(XmlBeanDefinitionReader reader)//XmlWebApplicationContext子类

                            1.3loadBeanDefinitions(String location, Set<Resource> actualResources)//类 AbstractBeanDefinitionReader

                             1.4 loadBeanDefinitions(EncodedResource encodedResource)  XmlBeanDefinitionReader XmlBeanDefinitionReader extends AbstractBeanDefinitionReader            

                             1.5 doLoadBeanDefinitions(inputSource, encodedResource.getResource())

                              1.6 registerBeanDefinitions(Document doc, Resource resource) //XmlBeanDefinitionReader 

                              1.7 registerBeanDefinitions(doc, createReaderContext(resource));//DefaultBeanDefinitionDocumentReader

                              1.8parseBeanDefinitions(root, this.delegate);//开始载入文档流进行解析//DefaultBeanDefinitionDocumentReader

                              1.9parseCustomElement(Element ele, BeanDefinition containingBd) 根据指定的namspace 去解析对应的数据{http://www.springframework.org/schema/context}例如这个就解析context:component-scan开头的标签 

//BeanDefinitionParserDelegate

                              2.0 handler.parse(ele, new ParserContext(this.readerContext, this, containingBd))//NamespaceHandlerSupport

//NamespaceHandlerSupport implements NamespaceHandler

                            2.1 findParserForElement(element, parserContext).parse(element, parserContext)//找到不同的解析器去处理解析到的内容// NamespaceHandlerSupport  BeanDefinitionParser parser = this.parsers.get(localName);

//BeanDefinitionParser 这个是解析器的接口



//判断是否有注解

if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {

   return false;

  }        

AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata 

//AnnotationMetadataReadingVisitor 类存放解析之后的类容

//将文件放到缓存的CachingMetadataReaderFactory 里面,同时将类的注解信息放到MetadataReader 里面

 AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);

 private MetadataReaderFactory metadataReaderFactory =  new CachingMetadataReaderFactory(this.resourcePatternResolver);

new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader())


public MetadataReader getMetadataReader(Resource resource) throws IOException {

  if (getCacheLimit() <= 0) {

   return super.getMetadataReader(resource);

  }

  synchronized (this.metadataReaderCache) {

   MetadataReader metadataReader = this.metadataReaderCache.get(resource);

   if (metadataReader == null) {

    metadataReader = super.getMetadataReader(resource);

    this.metadataReaderCache.put(resource, metadataReader);

   }

   return metadataReader;

  }

 }


 CachingMetadataReaderFactory extends SimpleMetadataReaderFactory



readClass(final InputStream is, boolean close)    //ClassReader //读取类的信息 


//AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata

 public AnnotationVisitor visitAnnotation(final String desc, boolean visible) {

  String className = Type.getType(desc).getClassName();

  this.annotationSet.add(className);

  return new AnnotationAttributesReadingVisitor(className, this.attributesMap, this.metaAnnotationMap, this.classLoader);

 } 


根据源文件的  SourceFile LoginController.java +Lorg/springframework/stereotype/Controller; !                    去判断注解了那些类



//PluggableSchemaResolver 获取所有schem 放到properties里面

getSchemaMappings(){

Properties mappings =

        PropertiesLoaderUtils.loadAllProperties(this.schemaMappingsLocation, this.classLoader);


}






0 0
原创粉丝点击