spring注解怎么解析(Spring详解)
- 软件开发
- 2023-08-13
- 78
各位老铁们好,相信很多人对spring注解怎么解析都不是特别的了解,因此呢,今天就来为大家分享下关于spring注解怎么解析以及Spring详解的问题知识,还望可以帮助...
各位老铁们好,相信很多人对spring注解怎么解析都不是特别的了解,因此呢,今天就来为大家分享下关于spring注解怎么解析以及Spring详解的问题知识,还望可以帮助大家,解决大家的一些困惑,下面一起来看看吧!
springboot跳转页面的注解是哪个
在SpringBoot中,用于跳转页面的注解是`@RequestMapping`,其主要作用是将HTTP请求映射到控制器的处理方法,并可以指定返回的视图名称或视图路径。
但是在SpringBoot2.0之后,为了规范,Spring官方推荐使用更为明确的注解`@GetMapping`、`@PostMapping`等来替代`@RequestMapping`来标记请求的方法。所以,一般情况下我们会使用`@GetMapping`注解来进行页面的跳转。
springboot 注解与程序的区别
springboot注解是注册解释,程序是有程序的
该如何学习spring源码以及解析bean定义的注册
如何学习spring源码前言
本文属于spring源码解析的系列文章之一,文章主要是介绍如何学习spring的源码,希望能够最大限度的帮助到有需要的人。文章总体难度不大,但比较繁重,学习时一定要耐住性子坚持下去。
获取源码
源码的获取有多种途径
GitHub
spring-framework
spring-wiki
可以从GitHub上获取源代码,然后自行编译
maven
使用过maven的都知道可以通过maven下载相关的源代码和相关文档,简单方便。
这里推荐通过maven的方式构建一个web项目。通过对实际项目的运行过程中进行调试来学习更好。
如何开始学习前置条件
如果想要开始学习spring的源码,首先要求本身对spring框架的使用基本了解。明白spring中的一些特性如ioc等。了解spring中各个模块的作用。
确定目标
首先我们要知道spring框架本身经过多年的发展现在已经是一个庞大的家族。可能其中一个功能的实现依赖于多个模块多个类的相互配合,这样会导致我们在阅读代码时难度极大。多个类之间进行跳跃很容易让我们晕头转向。
所以在阅读spring的源代码的时候不能像在JDK代码时一行一行的去理解代码,需要把有限的精力更多的分配给重要的地方。而且我们也没有必要这样去阅读。
在阅读spring某一功能的代码时应当从一个上帝视角来总览全局。只需要知道某一个功能的实现流程即可,而且幸运的是spring的代码规范较好,大多数方法基本都能见名知意,这样也省去了我们很多的麻烦。
利用好工具
阅读代码最好在idea或者eclipse中进行,这类IDE提供的很多功能很有帮助。
在阅读时配合spring文档更好(如果是自行编译源码直接看注释更好)。
笔记和复习
这个过程及其重要,我以前也看过一些spring的源码,但是好几次都是感觉比较吃力在看过一些后就放弃了。而由于没有做笔记和没有复习的原因很快就忘了。下次想看的时候还要重新看一遍,非常的浪费时间。
下面以IOC为例说明下我是怎么看的,供参考。
IOC入口:ApplicationContext
在研究源码时首先要找到一个入口,这个入口怎么选择可以自己定,当一定要和你需要看的模块有关联。
比如在IOC中,首先我们想到创建容器是在什么过程?
在程序启动的时候就创建了,而且在启动过程中大多数的bean实例就被注入了。
那问题来了,在启动的时候是从那个类开始的呢?熟悉spring的应该都知道我们平时在做单元测试时如果要获取bean实例,一个是通过注解,另外我们还可以通过构建一个ApplicationContext来获取:
在实例化ApplicationContext后既可以获取bean,那么实例化的这个过程就相当于启动的过程了,所以我们可以将ApplicationContext当成我们的入口。
ApplicationContext是什么
首先我们要明白的事我们平时一直说的IOC容器在Spring中实际上指的就是。
如果有看过我之前手写Spring系列文章的同学肯定知道在当时文章中充当ioc容器的是BeanFactory,每当有bean需要注入时都是由BeanFactory保存,取bean实例时也是从BeanFactory中获取。
那为什么现在要说ApplicationContext才是IOC容器呢?
因为在spring中BeanFactory实际上是被隐藏了的。ApplicationContext是对BeanFactory的一个封装,也提供了获取bean实例等功能。因为BeanFactory本身的能力实在太强,如果可以让我们随便使用可能会对spring功能的运行造成破坏。于是就封装了一个提供查询ioc容器内容的ApplicationContext供我们使用。
如果项目中需要用到ApplicationContext,可以直接使用spring提供的注解获取:
如何使用ApplicationContext
如果我们要使用ApplicationContext可以通过new该类的一个实例即可,定义好相应的xml文件。然后通过下面的代码即可:
ApplicationContext的体系
了解一个类,首先可以来看看它的继承关系来了解其先天的提供哪些功能。然后在看其本身又实现了哪些功能。
上图中继承关系从左至右简要介绍其功能。
ApplicationEventPublisher:提供发布监听事件的功能,接收一个监听事件实体作为参数。需要了解的可以通过这篇文章:事件监听ResourcePatternResolver:用于解析一些传入的文件路径(比如ant风格的路径),然后将文件加载为resource。HierarchicalBeanFactory:提供父子容器关系,保证子容器能访问父容器,父容器无法访问子容器。ListableBeanFactory:继承自BeanFactory,提供访问IOC容器的方法。EnvironmentCapable:获取环境变量相关的内容。MessageSource:提供国际化的message的解析配置文件的加载
Spring中每一个功能都是很大的一个工程,所以在阅读时也要分为多个模块来理解。要理解IOC容器,我们首先需要了解spring是如何加载配置文件的。
纵览大局
idea或者eclipse提供了一个很好的功能就是能在调试模式下看到整个流程的调用链。利用这个功能我们可以直接观察到某一功能实现的整体流程,也方便在阅读代码时在不同类切换。
以加载配置文件为例,这里给出整个调用链。
上图中下面的红框是我们写的代码,即就是我们应该开始的地方。下面的红框就是加载配置文件结束的地方。中间既是整体流程的实现过程。在阅读配置文件加载的源码时我们只需要关心这一部分的内容即可。
需要知道的是这里展示出来的仅仅只是跟这个过程密切相关的一些方法。实际上在这个过程中还有需要的方法被执行,只不过执行完毕后方法栈弹出所以不显示在这里。不过大多数方法都是在为这个流程做准备,所以基本上我们也不用太在意这部分内容
refresh()
前面的关于的构造函数部分没有啥好说的,在构造函数中调用了一个方法。该方法非常重要,在创建IOC容器的过程中该方法基本上是全程参与。主要功能为用于加载配置或这用于刷新已经加载完成的容器配置。通过该方法可以在运行过程中动态的加入配置文件等:
AbstractApplicationContext#refresh
这里将于当前功能不相关的部分删除掉了,可以看到进入方法后就会进入一个同步代码块。这是为了防止在同一时间有多个线程开始创建IOC容器造成重复实例化。
方法主要用于设置一些日志相关的信息,比如容器启动时间用于计算启动容器整体用时,以及设置一些变量用来标识当前容器已经被激活,后续不会再进行创建。
```
该方法首先判断是否已经实例化好BeanFactory,如果已经实例化完成则将已经实例化好的BeanFactory销毁。
然后通过new关键字创建一个BeanFactory的实现类实例,设置好相关信息。方法用于设置是否运行当beanName重复是修改bean的名称(allowBeanDefinitionOverriding)和是否运行循环引用(allowCircularReferences)。
```
```
就是读取配置文件并将其内容解析为一个Document的过程。解析xml一般来说并不需要我们特别的去掌握,稍微有个了解即可,spring这里使用的解析方式为Sax解析,有兴趣的可以直接搜索相关文章,这里不进行介绍。下面的才是我们需要关注的地方。
registerBeanDefinitions(Document,Resource)
在进入该方法后首先创建了一个的实例,这和之前的用于读取xml的reader类一样,只不过该类是用于从xml文件中读取。
Environment
在上面的代码中给Reader设置了Environment,这里谈一下关于Environment。
Environment是对spring程序中涉及到环境有关的一个描述集合,主要分为profile和properties。
profile是一组bean定义的集合,通过profile可以指定不同的配置文件用以在不同的环境中,如测试环境,生产环境的配置分开。在部署时只需要配置好当前所处环境值即可按不同分类加载不同的配置。
profile支持xml配置和注解的方式。
也可以通过注解配置:
然后在启动时根据传入的环境值加载相应的配置。
properties是一个很宽泛的定义,其来源很多如properties文件,JVM系统变量,系统环境变量,JNDI,servlet上下文参数,Map等。spring会读取这些配置并在environment接口中提供了方便对其进行操作的方法。
总之就是设计到跟环境有关的直接来找Environment即可。
handler
代码接着往下走,这一步很明显就是从解析好的document对象中读取BeanDefinition的过程,但是在此之前我们先要关注一下方法。
先来看一个XML文件。
上面是xml中根元素定义部分,可能平时并没有太多人注意。其属性中的xmlns是XMLNameSpace的缩写。namespace的作用主要是为了防止在xml定义的节点存在冲突的问题。比如上面声明了mvc的namespace:。在xml文件中我们就可以使用mvc了:
而实际上在spring中还根据上面定义的namespace来准备了各自的处理类。这里因为解析过程就是将xml定义的每一个节点取出根据配置好的属性和值来初始化或注册bean,为了保证代码可读性和明确的分工,每一个namespace通过一个专有的handler来处理。
跟踪方法,最终来到类的构造方法中。
可以看到默认的handler是通过一个本地文件来进行映射的。该文件存在于被依赖jar包下的META-INF文件夹下的spring.handlers文件中。
这里只是展示了beans包下的映射文件,其他如aop包,context包下都有相应的映射文件。通过读取这些配置文件来映射相应的处理类。在解析xml时会根据使用的namespace前缀使用对应的handler类解析。这种实现机制其实就是所谓的SPI(ServiceProviderInterface),目前很多的应用都在实现过程中使用了spi,如dubbo,mysql的jdbc实现等,有兴趣的可以取了解一下。
doRegisterBeanDefinitions(Element)
到这一步中间省略了一个方法,很简单没有分析的必要。
delegate
这里的delegate是对BeanDefinitionParse功能的代理,提供了一些支持解析过程的方法。我们可以看到上面有一个重新创建delegate同时又将之前的delegate保存的代码。注释上说是为了防止嵌套的beans标签递归操作导致出错,但是注释后面又说这并不需要这样处理,这个操作真的看不懂了,实际上我认为即使递归应该也是没有影响的。还是我理解错了?
创建好delegate后下面的if语句块就是用来判断当前加载的配置文件是否是当前使用的profile指定的配置文件。上面在介绍Environment的时候已经介绍过来,如果这里加载的配置文件和profile指定的不符则直接结束。
publicbooleanisDefaultNamespace(StringnamespaceUri){//BEANS_NAMESPACE_URI="http://www.springframework.org/schema/beans"return(!StringUtils.hasLength(namespaceUri)||BEANS_NAMESPACE_URI.equals(namespaceUri));}
```
接下来的可以算是我们本次目标最重要的一步了,前面所有的流程都是给这一步铺垫。通过该方法将解析出来的BeanDefinition注册到容器中,方便实例化。
方法接收两个参数holder和registry,如果有看过我手写系列的文章(IOC篇)应该知道,当时为了将bean定义和容器关联起来以及为了将的功能简化,所以我们定义了一个接口用于将注册到容器中和从容器中取,这里的registry功能也是一样的。(被实现,而实际就是容器)
而且可以看到实际上这里也是通过beanName来区分BeanDefinition是否重复(实际上肯定是我仿的spring的(笑)),只不过为了运行名称相同的BeanDefinition注册提供了alias,之前在实现ioc时没有实现这一步。
在方法的最后一步实际上是注册了一个listener,在一个被注册后触发,只不过上spring中实际触发方法是一个空方法,如果我们需要在注册完成后做一些什么工作可以直接继承后实现方法即可。
到这里基本上关于BeanDefinition的加载就完成了,后面就是重复上面的流程加载多个配置文件。
小结
本节主要介绍了我关于学习spring源码的一些方法,以及以spring的BeanDefinition的加载为例分析了其整体的流程,希望对大家能有所帮助。还要提的是spring源码很复杂,如果只是开断点一路调试下去肯定是不够的,看的过程中需要多做笔记。由于该文章内容较多以及本人水平问题,文章中可能会存在错误,如果有可以指出来方便修改。
springboot事务注解执行顺序
1.配置属性2.获取监听器,发布应用开始启动事件3.初始化输入参数4.配置环境,输出banner5.创建上下文6.预处理上下文7.刷新上下文8.再刷新上下文9.发布应用已经启动事件10.发布应用启动完成事件。
spring的事务注解作用于哪一层
作用在c等,既控制层。
springboot常用注解有哪些
springboot常用的注解有如下几个:
1、SpringBootApplication;
2、Repository;
3、Service;
4、RestController;
5、ResponseBody;
6、Component等
OK,关于spring注解怎么解析和Spring详解的内容到此结束了,希望对大家有所帮助。
本文链接:http://xinin56.com/ruanjian/6241.html