magento网站/百度词条官网入口

magento网站,百度词条官网入口,网站开发需求方案,北京it培训机构applicationContext文件加载和bean注册流程​ Spring对于从事Java开发的boy来说,再熟悉不过了,对于我们这个牛逼的框架的介绍就不在这里复述了,Spring这个大杂烩,怎么去使用怎么去配置,各种百度谷歌都能查到很多大牛教…

applicationContext文件加载和bean注册流程

​ Spring对于从事Java开发的boy来说,再熟悉不过了,对于我们这个牛逼的框架的介绍就不在这里复述了,Spring这个大杂烩,怎么去使用怎么去配置,各种百度谷歌都能查到很多大牛教程,但是,当我们按着教程一步步的把spring的开发框架搭建起来的时候,有没有一种想搞明白spring的冲动,万事开头难,就要从开头开始,而我认为spring开头就是如何加载配置文件,并初始化配置文件里面的bean当然也包括了我们用注解Service、Component等注解注解的bean,spring在容器启动的时候就要去加载这些内容,然后统一管理这些bean(统一管理的是他们的bean definition),这也就是spring的一个重要概念bean的容器。

​ applicationContext.xml到底是如何加载的呢?我把他简化成以下流程,当然了每个环节里Spring的实现都是错综复杂的,也是很佩服写Spring的大神。

29c244a4038fb90c617ddeb298638005.png

Spring初始化

​ 当我们初学Spring的教程的时候,教程里面肯定会有这样的一步操作,就是新建一个applicationContext.xml文件,当然了这是Spring里必须要有的一个文件,在这个文件里面我们可以进行bean的配置等等工作,让Spring来管理我们的Bean。然后,这个文件放在哪里也是个比较讲究的事情,可能对于初学者来说可额能会往WEB-INF文件夹一放就了事了,确实这样是可以的,因为Spring默认的位置就是这个,但是我们一般不这么做,一般会把这个文件放在resource里面,那这样子做的话,你就要指定位置,让Spring知道你这个文件的位置,这就有了下面一段代码,我们的Spring项目都会在web.xml配置这样的代码:

contextConfigLocationclasspath:applicationContext.xml

那问题来了,当项目启动的时候,spring是怎么去初始化应用的上下文的呢?答案就在类ContextLoader.java里面。当Tomcat启动时候会调用该类里面的一个方法public WebApplicationContext initWebApplicationContext(ServletContext servletContext),这个方法主要完成,根据我们在web.xml里面配置的contextConfigLocation初始化spring的web的应用上下文。具体看下改方法的实现(非完整代码,PS:由于太长了):

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {...... this.context = createWebApplicationContext(servletContext);//主要代码,创建web应用上下文  ...... configureAndRefreshWebApplicationContext(cwac, servletContext);//配置参数并调用初始化方法 ...... }

在这个方法里面有两句重要代码,第一句createWebApplicationContext(servletContext),这个会根据你配置的contextClass创建一个WebApplicationContext对象,但是我们一般不会配置这个参数,所以Spring默认会创建一个XMLWebApplicationContext对象,而这个就是后续操作的的重要对象,然后接下来一句重要代码configureAndRefreshWebApplicationContext(cwac, servletContext)这个就会去读取我们在web.xml里面配置的参数并set到变量里头去,这样Spring就能找到我们项目的applicationContext.xml文件了,到底如何找到下面会讲。接下来我们来看下configureAndRefreshWebApplicationContext方法的实现如下:

protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {if (ObjectUtils.identityToString(wac).equals(wac.getId())) {// The application context id is still set to its original default value// -> assign a more useful id based on available informationString idParam = sc.getInitParameter(CONTEXT_ID_PARAM);if (idParam != null) {wac.setId(idParam);}else {// Generate default id...wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +ObjectUtils.getDisplayString(sc.getContextPath()));}}wac.setServletContext(sc);String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);if (configLocationParam != null) {wac.setConfigLocation(configLocationParam);}// The wac environment's #initPropertySources will be called in any case when the context// is refreshed; do it eagerly here to ensure servlet property sources are in place for// use in any post-processing or initialization that occurs below prior to #refreshConfigurableEnvironment env = wac.getEnvironment();if (env instanceof ConfigurableWebEnvironment) {((ConfigurableWebEnvironment) env).initPropertySources(sc, null);}customizeContext(sc, wac);wac.refresh();}

在这个方法中我们只要关注两个地方,第一个:

String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);if (configLocationParam != null) {wac.setConfigLocation(configLocationParam);}

这块代码块就是,讲我们配置在web.xml里面的参数set到我们的变量中去。第二个地方就是:

wac.refresh();

调用这个执行后续的加载文件操作等后续操作。

Spring是如何找到applicationContext.xml文件

​ 其实,从refresh到Spring里去查找配置文件路径之间,有很多步骤,这些也都要花点时间去理解的,在这里不展开讲,我们只要知道,XmlWebApplicationContext会委托给XmlBeanDefinitionReader类去解析配置文件,在XmlWebApplicationContext类里面有个方法loadBeanDefinitions如下:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {String[] configLocations = getConfigLocations();if (configLocations != null) {for (String configLocation : configLocations) {reader.loadBeanDefinitions(configLocation);}}}

欢迎工作一到五年的Java工程师朋友们加入Java程序员开发: 721575865

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!

该方法就是将一个个的配置文件委托给XmlBeanDefinitionReader去解析配置文件,但是解析之前有句代码String[] configLocations = getConfigLocations();这个就是查找我们的配置的文件的方法,

protected String[] getConfigLocations() {return (this.configLocations != null ? this.configLocations : getDefaultConfigLocations());}

实现很简单,就是我们有配置该位置地址就会去读我们配置的路径,否则就会去读默认的配置文件路径,这就是开篇说到的要是没配置路径也能读取到配置文件,前提就是要跟Spring默认定义好的文件路径及文件名保持一致才行。getDefaultConfigLocations函数的实现也很简单:

/** Default config location for the root context */public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";/** Default prefix for building a config location for a namespace */public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";/** Default suffix for building a config location for a namespace */public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";protected String[] getDefaultConfigLocations() {if (getNamespace() != null) {return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};}else {return new String[] {DEFAULT_CONFIG_LOCATION};}}

如果配置了namespace就会去找这个名字的xml配置文件,如果没有配置就去找默认的配置文件。所以不管如何,这个配置文件是必须在spring项目中的。至此,配置文件基本将完,接下来就是重头戏了,就是解析xml以及xml里面的节点,并注册到spring的bean容器中去。

将xml文件转成Document处理对象

如何将xml转成Document对象,这个也是很复杂的操作,首先将resource读取InputStream流,在将InputStream流包装成InputSource对象,在处理成Document对象,直接上代码:

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {Assert.notNull(encodedResource, "EncodedResource must not be null");if (logger.isInfoEnabled()) {logger.info("Loading XML bean definitions from " + encodedResource.getResource());}Set currentResources = this.resourcesCurrentlyBeingLoaded.get();if (currentResources == null) {currentResources = new HashSet(4);this.resourcesCurrentlyBeingLoaded.set(currentResources);}if (!currentResources.add(encodedResource)) {throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");}try {InputStream inputStream = encodedResource.getResource().getInputStream();//获取流try {InputSource inputSource = new InputSource(inputStream);if (encodedResource.getEncoding() != null) {inputSource.setEncoding(encodedResource.getEncoding());}return doLoadBeanDefinitions(inputSource, encodedResource.getResource());}finally {inputStream.close();}}catch (IOException ex) {throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), ex);}finally {currentResources.remove(encodedResource);if (currentResources.isEmpty()) {this.resourcesCurrentlyBeingLoaded.remove();}}}

接下来又到doLoadBeanDefinitions(inputSource, encodedResource.getResource());方法去了,该方法就是生成Doucument对象的,然后就是解析具体的节点了,部分源码如下:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {Document doc = doLoadDocument(inputSource, resource);//这就是解析成Document对象的操作return registerBeanDefinitions(doc, resource);......}

解析Document不展开讲了,不是本篇的重点,重点是下面的,spring如何解析xml文件的bean及注解的bean然后注册到容器中去,registerBeanDefinitions(doc, resource)是下面的重点。

解析Document里面的节点

XmlBeanDfinitionReader本身又不是直接取解析document的,他是委托给了DefaultBeanDefinitionDocumentReader类去实现,源代码中,会去创建DefaultBeanDefinitionDocumentReader对象实例,然后调用实例的注册方法,代码如下:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();int countBefore = getRegistry().getBeanDefinitionCount();documentReader.registerBeanDefinitions(doc, createReaderContext(resource));return getRegistry().getBeanDefinitionCount() - countBefore;}

首先,我们必须知道,spring的xml文件里面有两种类型的节点,一种是默认节点,相对于默认节点之外的节点统称自定义节点,这可以从源码里面知道,而默认节点有以下几个:beans、import、alias、bean这几个节点是默认节点,而相对于这几个节点之外的都是默认节点,applicationContext里面有几个自定义节点,如下:property-placeholder、property-override、annotation-config、component-scan、load-time-weaver、spring-configured、mbean-export、mbean-server,这里面常见的有component-scan等,为什么spring要分成默认和自定义节点呢,是因为自定义节点都有特定的业务,比如component-scan,他是去扫描程序包,加载用注解定义的bean,例如开发中的service等bean,所以这些自定义节点都配备了解析器,这些解析器预先初始化好的,解析到什么节点就去获取相应的解析器去处理相应的业务,自定义节点解析器配置如下:

@Overridepublic void init() {registerBeanDefinitionParser("property-placeholder

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/338901.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言数据类型转换

首先变量的数据类型是可以转换的。转换的方法有两种,一种是自动转换,另一种是强制转换。自动转换即当不同类型的数据进行混合运算时,编译系统将按照一定的规则自动完成。而强制类型转换是由程序员通过编程强制转换数据的类型。自动转换的规则…

java 类持久化_Java 持久化之 -- IO 全面整理(看了绝不后悔)

目录:一、java io 概述什么是IO?IO包括输入流和输出流,输入流指的是将数据以字符或者字节形式读取到内存 分为字符输入流和字符输入流输入流指的是从内存读取到外界 ,分为字符输入流和字节输出流Java IO即Java 输入输出系统。不管…

idea 找不到或无法加载主类_解决IDEA中Groovy项目no Groovy library is defined的问题

实验环境IDEA2019.1.2Groovy-2.5.8错误重现新建了一个Groovy工程,指定了groovy版本,如图新建了一个简单的Groovy Class,运行,出现如下错误错误的尝试(以下是试错过程,并不能解决问题,读者可以不要跟着操作&…

C语言标识符、关键字和注释

这一节主要讲解C语言中的几个基本概念。标识符定义变量时,我们使用了诸如“a”“abc”“mn123”这样的名字,它们都是程序员自己起的,一般能够表达出变量的作用,这叫做标识符(Identifier)。标识符就是程序员…

java 类.class_面试官:Java反射是什么?我回答不上来!

一.概念反射就是把Java的各种成分映射成相应的Java类。Class类的构造方法是private,由JVM创建。反射是java语言的一个特性,它允程序在运行时(注意不是编译的时候)来进行自我检查并且对内部的成员进行操作。例如它允许一个java的类获取他所有的成员变量和…

巧解C语言运算符的优先级和结合性

本篇文章我们从一个例子入手讲解,请看下面的代码:#include int main(){ int a 16, b 4, c 2; int d a b * c; int e a / b * c; printf( "d%d, e%d\n", d, e); return 0; }运行结果:d24, e81) 对于表达式a b * c&#xff0…

jms mdb_MDB!= JMS,反之亦然

jms mdb基本 消息驱动Bean(又称为MDB)只是另一个EJB,例如无状态,有状态或单例。 使用MessageDriven批注指定。 MDB用于异步消息处理 它们与无状态EJB 相似 ,因为它们都是由EJB容器池化的 但是,它们与无状…

C语言中的三目运算符是啥?有何用处?

一般来说,C语言中的三目运算符为a?b:c即有三个参与运算的量。由条件运算符组成条件表达式的一般形式为:表达式1? 表达式2:表达式3求值规则为:如果表达式1的值为真,则以表达式2 的值作为条件表达式的值,否…

status_code想要得到302却得到200_中考200天倒计时!教你高效规划!抓紧抢报预留座位!...

教育点击右上方蓝字关注金石教育金石教育青岛站推送青岛教育资讯,关注孩子成长关注教育主讲人——段莲1、金石教育首席学习规划师:在中考规划行业,段莲老师已经深入研究多年,了解最新的中考数据,并且能够把握住每个数据…

gui jfr_Java飞行记录器(JFR)

gui jfrJFR是一个Java分析器,它使您可以研究代码的运行时特征。 通常,您将使用探查器来确定代码的哪些部分导致大量内存分配或导致消耗过多的CPU。 有很多产品在那里。 过去,我使用过YourKit,OptimizeIt,JProfiler&am…

java 命名内部类_如何把java SWT程序中的匿名内部类改写成命名内部类?

展开全部//请看最后一个e69da5e6ba9062616964757a686964616f31333363386134private class ,其实命名内部类跟普通的java程序一样写,只要知道你自己的监听器要继承于哪个类,实现什么方法public class Level4Class extends ViewPart {private TableViewer …

C语言 | 递增运算符

如何灵活使用C语言递增运算符。 解题思路:自增运算符 使操作数的值加1,其操作数必须为可变左值(可简单地理解为变量)。对于自增就是加1这一点,读者应该不会有什么疑问。难点在于: 可以置于操作数前面&#…

数据结构实验之图论四:迷宫探索_迷宫搜索类的双向bfs问题(例题详解)

前言文章若有疏忽还请指正!更多精彩还请关注公众号:bigsai头条号:一直码农一直爽在搜索问题中,以迷宫问题最具有代表性,无论是八皇后的回溯问题,还是dfs找出口,bfs找最短次数等等题目的问题。在…

ngrok服务器搭建_利用暴露在外的API,无法检测的Linux恶意软件将矛头指向Docker服务器...

K8s已经成为一线大厂分布式平台的标配技术。你是不是还在惆怅怎么掌握它?来这里,大型互联网公司一线工程师亲授,不来虚的,直接上手实战,3天时间带你搭建K8s平台,快速学会K8s,点击下方图片可了解…

干货 | C语言系列3——常量,运算符,常用数学函数......

符号常量和const常量1.符号常量符号常量通俗来讲就是“替换”,又称为宏定义。格式如下:#define 标识符 常量宏定义可以定义单个变量为常量,也可以定义某个语句或片段。宏定义有一点需要特别注意,它只是“机械”替换,并…

javafx 浏览器_浏览器中的JavaFX

javafx 浏览器浏览器中的JavaFX屏幕截图 最近,Carl Dea和我启动了一个新项目,将JavaFX 8引入浏览器。 今天,我想介绍我们创建的前两个概念验证,以查看该想法是否完全可行。 对于不耐烦的人,这里是到PoC的链接。 但请注…

javafx 示例_JavaFX列表示例

javafx 示例这是使用JavaFX构建的示例列表应用程序。 该应用程序是待办事项列表。 该应用程序具有添加,更新和删除列表中项目的功能。 列表数据存储在HSQLDB关系数据库中。 该应用程序使用JDBC(Java数据库连接)API访问数据库。 该应用程序打包…

嵌入式C语言的7个硬核知识

1void 与 void*void表示的是无类型,不可以采用这个类型声明变量或常量,但是可以把指针定义为void类型,如void* ptr。void指针可以指向任意类型的数据,可用任意数据类型的指针对void指针赋值,比如int *ptrInt&#xff1…

C语言指针用得好犹如神助!这些使用技巧值得收藏

指针用的好犹如神助,用不好会让你叫苦连连,但大多数人是用不好指针的,所以后来的很多语言都把指针封装,屏蔽。比如JAVA,java是没有指针的,但是很多地方都用到指针,不过不对用户开放,…

wso2_使用WSO2开发

wso2几个月以来,我又开始使用WSO2产品。 在接下来的文章中,我描述了我遇到的一些(小)问题以及如何解决它们。 设置开发环境时,我要做的第一件事是在Mac上下载Developer Studi o(64位版本)。 解…