Spring

什么是spring

spring是一个轻量级的容器框架,目的是简化企业应用开发,核心有两大功能IOC和AOP,通过IOC可以帮助我们管理项目中对象依赖,通过AOP可以帮助我们动态增强应用的功能性。spring对现有主流框架都有集成的支持,让我们我们很容易的在应用中使用其他框架的功能。

什么是IOC

控制反转,IOC其实就是对象的生命周期交给spring管理,spring本身是一个bean容器,帮助我们创建并且缓存对象引用,当我们需要某个对象的时候,由spring进行创建;过程中需要DI依赖注入,将我们需要的对象引用赋值给变量,降低组件之间耦合性;对象与对象之间复杂的引用关系也由spring帮我们管理;第三方功能需要的对象也由spring帮我们管理,我们只需要拿来即用就好。

什么是AOP

面向切面,切面指不同功能不同业务中相同的一部分逻辑,比如鉴权、日志、事务等模块,aop可以帮助我们轻易的在每个业务中进行这些通用功能的拓展,让我们只专注于实现业务功能即可。
当你需要在很多方法或接口上增加相同或相似的逻辑时,可以考虑使用AOP。
AOP有两种实现方式Spring的实现和AspectJ的实现,AspectJ是早期的aop实现,定义了一些标准的枚举,这些枚举spring也在使用,AspectJ的实现方式是使用静态代理增强,在代码编译期间将切面逻辑织入对象;spring是通过动态代理,JDK或者CGlib,在对象创建期间。

AOP中的概念

连接点(Join point) 被切入的执行中的方法
切点(pointcut) 定义的一组被切入的方法
通知(advice) 在连接点上执行的方法包括Around、Before、After、After returning、After throwing
切面(aspect) 被提取的公共模块 切面就是一个pointcut + 一组advice
目标对象(target) 包含连接点的对象
织入(Weaving) 通过代理等方法,在target的join point中执行advice

AOP实现的方式

spring实现的AOP,动态代理,jdk面向接口、cglib子类继承,对象创建期间、getBean

AspectJ实现的AOP,静态代理增强,代码编译期间将切面逻辑织入对象

什么是spingmvc

springmvc是spring提供的web应用框架,采用mvc模式modile-view-controller,springmvc本身是spring拓展出来的一个模块,spring对他提供很好的继承支持,通过@Controller和@RequestMapping我们可以很简单的创建一个web接口,核心dispatcherservlet拦截所有请求,根据uri找到对应的handler方法并执行,返回对应视图数据。

springmvc组件

  • Handler Handler包装了具体的业务逻辑,一个RequestMapping、servlet可以看做一个handler
  • HandlerMapping 用来查找Hanlder,每个请求都由对应的handler进行处理,reqeust找到HandlerExecutionChain,HandlerExecutionChain包含了一个Handler和一组Interceptors
  • HandlerAdapter Handler适配器,用来适配项目中老的servlet候着controller,适配器模式,
  • HandlerExceptionResolver 全局异常解析
  • ViewResolver 视图解析器,根据handler返回的ModleAndView找到对应的页面进行渲染,可以是jsp、html或者直接输出
  • MultipartResolver 处理上传文件的请求,普通的request包装成MultipartHttpServletRequest,后者可以直接调用getFile方法获取File

springmvc运行原理

springmvc启动的时候会创建自己的上下文applicationcontext对象,将所有controller信息载入上下文,一个reqeustmapping就是一个contoller

  1. 客户端请求提交到DispatcherServlet
  2. 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller
  3. DispatcherServlet将请求提交到Controller
  4. Controller调用业务逻辑处理后,返回ModelAndView
  5. DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图
  6. 视图负责将结果显示到客户端

springmvc中拦截器和过滤器的区别

过滤器是Servlet定义的规范、由servlet容器进行实现,拦截器是由springmvc定义并且实现的
过滤器在servlet之前调用,拦截器存储在HandlerExecutionChain中,在DispatcherServlet中调用
过滤器拦截所有请求,拦截器只能拦截定义的handler
过滤器是责任链模式,拦截器是代理模式(静态代理的)

什么是springboot

本质上springboot还是spring,在spirng的基础上做了一些更方便我们搭建项目的功能,让我们在编码、配置、部署、监控等方面变的更简单了。
基于约定大于配置的自动装配,我们减少了很多配置项,starter帮助我们更简单的管理依赖,内置servlet容器,让我们更快的启动部署一个应用。

什么是springcloud

springcloud是spring提出的一套关于微服务架构的组件,包含网关、注册中心、配置中心、RPC、熔断降级、负载均衡、mq、分布式事务等组件

spring启动过程

spring的启动过程在AbstractApplicationContext.refresh()方法中执行

  1. prepareRefresh(); 准备上下文刷新 准备一些集合容器
  2. *创建Bean工厂ConfigurableListableBeanFactory
  3. 在使用之前准备一下BeanFactory内部的一些信息 环境参数等
  4. *postProcessBeanFactory 允许子类对BeanFactory做一些后置处理,模板方法
  5. *invokeBeanFactoryPostProcessors 执行Bean工厂后置处理器 会加载BeanDefinition
  6. *registerBeanPostProcessors 注册Bean后置处理器
  7. initMessageSource 初始化消息源
  8. initApplicationEventMulticaster 初始化应用事件广播器
  9. *onRefresh 正在refresh,模板方法,交由子类实现,ServletWebServerApplicationContext会在此处创建web服务器
  10. registerListeners 注册观察者们
  11. *finishBeanFactoryInitialization 根据BeanDefinition实例化所有Bean对象
  12. *finishRefresh 完成刷新 推送event消息,ServletWebServerApplicationContext重写此方法,增加了启动web服务器的逻辑

beandefinition作用

beandefinition是Bean定义信息,spring依靠beandefinition进行实例化,在spring容器启动执行invokeBeanFactoryPostProcessors方法时会扫描路径上的所有Bean对象,加载他们的BeanDefinition信息到BeanFactory中,后面会根据这些信息进行Bean的实例化

springboot启动过程

  • 实例化部分 new SpringApplication
    从spring.factories文件中加载一些ApplicationContextInitializer、ApplicationListener;根据是否引用了某些class推测应用类型;设置一下运行主类
  • 启动部分
    从spring.factories文件中加载SpringApplicationRunListener,这个监听器是springboot启动过程的一些事件推送
    创建ConfigurableApplicationContext上下文 这里会根据推测的应用类型选择创建对应的子类实现
    准备上下文 加载一些环境信息、启动参数信息等
    执行上下文刷新启动spring
    执行结束

spring中bean加载过程

实例化Bean 通过反射调用class的构造方法或者通过@Bean设置的实例化方法 此时Bean对象所有属性都是默认值
为Bean对象进行属性填充 这个阶段会遇到循环依赖问题 注入自定义对象
为Bean对象填充awera信息 注入上下文对象
执行BeanPostProcessor前置方法
执行init方法
执行BeanPostProcessor后置方法
将Bean放入BeanFactory

所有BeanPostProcessor都会在aware之后执行么

有一些BeanPostProcessor会提前到populateBean阶段执行
AOP、Autowaire、dubbo的Refrence
InstantiationAwareBeanPostProcessor
DestructionAwareBeanPostProcessor
MergedBeanDefinitionPostProcessor

spring解决循环依赖

spring循环依赖问题:spring中交由BeanFactory创建Bean对象,而创建Bean对象过程中有可能依赖了其他对象也需要创建,如果两个对象互相依赖那么创建过程就会进入一个死循环;单缓存无法解决,是因为对象没有创建完毕就放入缓存是不安全的;双缓存可以解决,但是对于aop无法处理,spring实现aop是在BeanPostProcessor阶段,如果强行处理就需要把aop提前到Bean实例化阶段,侵入了标准Bean的创建;三级缓存解决aop动态代理问题
解决方法:
A对象实例化之后创建一个ObjectFactory放入三级缓存,ObjectFactory是一段lambda表达式,执行了获取A对象最终引用的代码,过程中执行一些BeanPostProcessor处理包括AOP;
A对象属性填充阶段加载B对象,实例化B对象之后也放入三级缓存,进入B的属性填充,B的属性填充阶段需要加载A对象,从三级缓存取出对象引用放入二级缓存,并执行属性填充;
B属性填充等一些列代码执行完毕后,将B对象的从三级缓存取出放入一级缓存;
A对象拿到B的引用,进行属性填充完毕,从二级缓存出去放入一级缓存

springmvc父子容器

springmvc启动的时候,加载DispatcherServlet的时候会再创建一个ApplictionContext,并将Spring已经创建的向下文设置为父级,形成父子容器
父子容器的存在主要是为了划分边界,service层我们使用spring框架,对象功能由spring帮我们管理,而在web层可能存在多实现,比如springmvc struts2,父子容器可以帮助我们很容易的替换web层,只需要将spring-servlet.xml替换成Struts的配置文件struts.xml,service层都不用动。
控制扫描路径,来规避父子容器扫描的Bean对象
SpringBoot中使用的是同一个容器,将DispatcherServlet作为一个Bean对象交由Spring启动了,以前是交由tomcat启动。

springmvc常用注解

@Controller 标记是一个contoller
@RequestMapping 标记资源路径
@RequestParam 标记参数名称,必填
@RequestAttribute 标记属性名称,必填
@RequestBody 标记参数是Json体
@ResponseBody 标记返回时Json体
@RestController 标记controller内部全是json方法
@WebFilter 过滤器
@CrossOrigin 标记请求与

spring加载bean的几种方式

@Component
@Configuration
<bean/>
@Bean
<import/>
@Import
ImportSelector接口
ImportBeanDefinitionRegistrar接口

springboot自动装配原理

springboot自动为我们创建一些Bean对象,基于约定大于配置的原则,按照默认值去创建。
@SpringBootApplication修饰了启动类,@SpringBootApplication包含@EnableAutoConfiguration
@EnableAutoConfiguration包含@Import(AutoConfigurationImportSelector.class)
所有需要自动装配的类是依靠AutoConfigurationImportSelector,从spring.factories文件中加载所有配置为EnableAutoConfiguration的类
装配时机是在启动时,context.refresh()中,执行BeanFacotoryPostProcessor阶段,通过ConfigurationClassPostProcessor加载

springboot内嵌tomcat原理

  1. SpringApplication在实例化阶段会根据路径上引用的一些class推测当前应用的类型,如果存在Servlet或者ConfigurableWebApplicationContext会被推测为是一个web服务器;
  2. SpringApplication.run阶段创建上下文时,会根据上面推测的应用类型创建具体的上下文,这里会创建AnnotationConfigServletWebServerApplicationContext
  3. 这个context在refresh阶段的onRefresh中会创建webServer,默认是tomcat,加载的ServletWebServerFactory默认是tomcat的,根据是否引用了内置tomcat其他的还有jetty、Undertow
    TomcatServletWebServerFactory是通过ServletWebServerFactoryAutoConfiguration自动装配的,条件是路径上有Tomcat、Servlet
  4. 在refresh阶段的finishRefresh中会启动webServer

spring和springboot中提供了哪些扩展点

BeanFactoryPostProcessor Bean工厂后置处理器 可以通过ApplicationContextInitializer加载,或者只要在refresh方法之前通过listener加载
BeanPostProcessor Bean后置处理器
ApplicationRunListener 广播springboot启动事件
ApplicationListener 广播spring启动事件

ApplicationContextInitializer在什么时机执行

SpringApplication.run.prepareContext;

springboot的starter原理

管理依赖,省去了以前引入一大堆依赖,还要梳理版本,弄不好就会冲突,
自动装配组件,省去了一大堆配置
统一配置文件,将所有配置统一到spring的配置文件中,便于管理

手写starter

一般分为两个包 一个starter包负责引入依赖,一个autoconfiguration包负责自动装配组件
starter包不需要任何代码,只引入依赖
autoconfiguration包定义配置类,定义组件Bean,自动装配
配置文件类:使用@ConfigurationProperties(prefix = "demo")修饰的Java类,属性名就是配置名
自动配置类:@EnableConfigurationProperties(DemoProperties.class)修饰的Java类,会自动读取spring配置文件中对应配置信息
定义组件:完成核心业务,并用@Bean等方式定义为一个Bean对象
自动装配:在META-INF目录下添加spring.factories,并配置org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx.DemoAutoConfiguration

BeanFactory和ApplicationContext

BeanFactory是bean工厂,ApplicationContext是应用上下文
ApplicationContext实现了BeanFactory通过门面模式支持了BeanFactory中的方法,内部引用了一个DefaultListabledBeanFactory
ApplicationContext还负责整个应用的生命周期,BeanFactory只管Bean对象

BeanFactory和FactoryBean

BeanFactory是bean工厂,简单工厂模式;
FactoryBean是一个Bean,工厂方法模式,getBean方法中对其特殊处理,如果是FactoryBean实现类并且非急切加载的话,会后置处理,当获取FactoryBean时会自动调用getOBject方法,如果需要FactoryBean对象,需要getBean("&"+name),用于懒加载对象,或加载复杂对象实现,比如

spring中的设计模式

Listener 观察者模式
HandlerAdapter 适配器模式
AOP 代理模式
ApplicationContext 门面模式
AbstractApplicationContext.refresh() 模板方法
BeanFactory 简单工厂
FactoryBean和ObjectBean 工厂方法
Waraper 装饰模式

springcloud有哪些组件

网关 配置中心 注册中心 服务调用RPC 负载均衡 熔断降级 限流 路由 分布式消息 分布式事务

spring中的事务

基于AOP + Threadlocal实现

spring中的事务传播

required 如果存在就加入,如果没有就创建
supports 如果存在就加入,如果没有就非事务执行
not_supports 如果存在就挂起,非事务执行
required_new 如果存在就挂起,开启一个新事物执行
mandatory 如果不存在事务,抛异常
never 如果存在事务,抛异常
nested 嵌套事物,子事务不影响父,父回滚,子回滚

spring中事务失效的场景

私有方法、final方法、多线程调用、非spring管理对象、直接调用、吞异常、数据库不支持事务、

@Resouce和@Autowire的区别

resouce getBeanByName J2ee注解
autowire getBeanByType spring注解 配合@Qualifier根据name加载;可以装配多个实例到集合或者map

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容