Spring学习(下)

7. Spring中的设计模式

Spring 框架中广泛使用了不同类型的设计模式,下面我们来看看到底有哪些设计模式?

  1. 工厂设计模式 : Spring 使用工厂模式通过 BeanFactory、ApplicationContext 创建 bean 对象。
  2. 代理设计模式 : Spring AOP 功能的实现。
  3. 单例设计模式 : Spring 中的 Bean 默认都是单例的。
  4. 模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate 等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
  5. 包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
  6. 观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
  7. 适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。

8. Spring循环依赖

8.1 简说循环依赖

Spring循环依赖:说白了就是一个或多个对象实例之间存在直接或间接的依赖关系,这种依赖关系构成了构成一个环形调用。发生循环依赖的两个前提条件是:

出现循环依赖的Bean必须要是单例(singleton),如果依赖prototype则完全不会有此需求。

依赖注入的方式不能全是构造器注入的方式,只能解决setter方法的循环依赖,这是错误的。

假设AB之间相互依赖,通过尝试不同的注入方式注入后可的如下结论:

PS:第四种可以而第五种不可以的原因是 Spring在创建Bean时默认会根据自然排序进行创建,所以A会先于B进行创建。

8.2 循环依赖通俗说

Spring通过三级缓存解决了循环依赖。

  1. 一级缓存 : Map<String,Object> singletonObjects,单例池,用于保存实例化、注入、初始化完成的bean实例
  2. 二级缓存 : Map<String,Object> earlySingletonObjects,早期曝光对象,用于保存实例化完成的bean实例
  3. 三级缓存 : Map<String,ObjectFactory<?>> singletonFactories,早期曝光对象工厂,用于保存bean创建工厂,以便于后面扩展有机会创建代理对象。

当A、B两个类发生循环引用时,在A完成实例化后,就使用实例化后的对象去创建一个对象工厂,并添加到三级缓存中,如果A被AOP代理,那么通过这个工厂获取到的就是A代理后的对象,如果A没有被AOP代理,那么这个工厂获取到的就是A实例化的对象。当A进行属性注入时,会去创建B,同时B又依赖了A,所以创建B的同时又会去调用getBean(a)来获取需要的依赖,此时的getBean(a)会从缓存中获取:

第一步,先获取到三级缓存中的工厂。

第二步,调用对象工工厂的getObject方法来获取到对应的对象,得到这个对象后将其注入到B中。紧接着B会走完它的生命周期流程,包括初始化、后置处理器等。

当B创建完后,会将B再注入到A中,此时A再完成它的整个生命周期。至此循环依赖结束!

8.3 三级缓存意义何在?

先跟踪下源码(如上图),跟踪过程中注意区别下有AOP的依赖没有AOP的依赖两种情况,跟踪后你会发现三级缓存的功能是只有真正发生循环依赖的时候,才去提前生成代理对象,否则只会创建一个工厂并将其放入到三级缓存中,但是不会去通过这个工厂去真正创建对象。至于提速这一说法,还是拉闸吧。

面试官:关于Spring就问这13个点(下)

如上图所示,如果使用二级缓存解决循环依赖,意味着所有Bean在实例化后就要完成AOP代理,这样违背了Spring设计的原则,Spring在设计之初就是通过AnnotationAwareAspectJAutoProxyCreator这个后置处理器来在Bean生命周期的最后一步来完成AOP代理,而不是在实例化后就立马进行AOP代理。

9. Spring事务

Spring 事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。Spring只提供统一事务管理接口,具体实现都是由各数据库自己实现,数据库事务的提交和回滚是通过binlog或者undolog实现的,具体流程在MySQL中讲过了。Spring会在事务开始时,根据当前环境中设置的隔离级别,调整数据库隔离级别,由此保持一致。

9.1 Spring事务的种类

Spring 支持编程式事务管理和声明式事务管理两种方式:

  1. 编程式事务

编程式事务管理使用TransactionTemplate。

  1. 声明式事务

声明式事务管理建立在AOP之上的。其本质是通过AOP功能,对方法前后进行拦截,将事务处理的功能编织到拦截的方法中,也就是在目标方法开始之前启动一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

优点是不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明或通过@Transactional注解的方式,便可以将事务规则应用到业务逻辑中,减少业务代码的污染。唯一不足地方是,最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。

9.2 Spring的事务传播机制

spring事务的传播机制说的是,当多个事务同时存在的时候,spring如何处理这些事务的行为。事务传播机制实际上是使用简单的ThreadLocal实现的,所以,如果调用的方法是在新线程调用的,事务传播实际上是会失效的。

  1. propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择,也是默认模式,它适合于绝大多数情况。
  2. propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
  3. propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。
  4. propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
  5. propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  6. propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
  7. propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作

9.3 Spring的事务隔离级别

TransactionDefinition接口中定义了五个表示隔离级别的常量,这里其实关键还是要看MySQL的隔离级别:

  1. ISOLATION_DEFAULT:使用后端数据库默认的隔离界别,MySQL默认可重复读,Oracle默认读已提交。
  2. ISOLATION_READ_UNCOMMITTED:读未提交。
  3. ISOLATION_READ_COMMITTED:读已提交。
  4. ISOLATION_REPEATABLE_READ:可重复读。
  5. ISOLATION_SERIALIZABLE:串行化。

10. Spring MVC

10.1 什么是 MVC ?

MVC模式中M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将 M 和 V 的实现代码分离,开发中一般将应用程序分为 Controller、Model、View 三层,Controller 接收客户端请求,调用 Model 生成业务数据,传递给 View,View最终展示前端结果。

Spring MVC 就是对上述这套流程的封装,屏蔽了很多底层代码,开放出接口,让开发者可以更加轻松、便捷地完成基于 MVC 模式的 Web 开发。

10.2 Spring 跟 Spring MVC关系

最开始只有Spring,只提供IOC跟AOP核心功能,后来出了乱七八糟的比如MVC、Security、Boot 等。原来的Spring 就变成了现在的Spring Core,MVC指的是Web的MVC框架。

Spring MVC 就是一个MVC框架,其实大范围上来说属于Spring,Spring MVC是一个类似于Struts的MVC模式的WEB开发框架,Spring MVC是基于 Spring 功能之上添加的 Web 框架,Spring 跟 SpringMVC可以理解为父子容器的关系,想用 Spring MVC 必须先依赖Spring。

Spring MVC 是控制层,用来接收前台传值,调用service层和持久层,返回数据再通过 Spring MVC把数据返回前台

10.3 Spring MVC 的核心组件

DispatcherServlet:前置控制器,是整个流程控制的核心,控制其他组件的执行,进行统一调度,降低组件之间的耦合性,相当于总指挥。

Handler:处理器,完成具体的业务逻辑,相当于 Servlet 或 Action。

HandlerMapping:DispatcherServlet 接收到请求之后,通过 HandlerMapping 将不同的请求映射到不同的 Handler。

HandlerInterceptor:处理器拦截器,是一个接口,如果需要完成一些拦截处理,可以实现该接口。

HandlerExecutionChain:处理器执行链,包括两部分内容:Handler 和 HandlerInterceptor(系统会有一个默认的 HandlerInterceptor,如果需要额外设置拦截,可以添加拦截器)。

HandlerAdapter:处理器适配器,Handler 执行业务方法之前,需要进行一系列的操作,包括表单数据的验证、数据类型的转换、将表单数据封装到 JavaBean 等,这些操作都是由 HandlerApater 来完成,开发者只需将注意力集中业务逻辑的处理上,DispatcherServlet 通过 HandlerAdapter 执行不同的 Handler。

ModelAndView:装载了模型数据和视图信息,作为 Handler 的处理结果,返回给 DispatcherServlet。

ViewResolver:视图解析器,DispatcheServlet 通过它将逻辑视图解析为物理视图,最终将渲染结果响应给客户端。

10.4 Spring MVC 的工作流程

DispatcherServlet 表示前置控制器,是整个SpringMVC的控制中心。用户发出请求,接收请求并拦截请求。

HandlerMapping 为处理器映射。DispatcherServlet调用 HandlerMapping,HandlerMapping根据请求url查找Handler。

HandlerExecution 表示具体的Handler,其主要作用是根据url查找控制器,如上url被查找控制器为:hello。

HandlerExecution 将解析后的信息传递给 DispatcherServlet,如解析控制器映射等。

HandlerAdapter 表示处理器适配器,其按照特定的规则去执行Handler。

Handler 让具体的 Controller 执行。

Controller 将具体的执行信息返回给 HandlerAdapter,如ModelAndView。

HandlerAdapte r将视图逻辑名或模型传递给 DispatcherServlet。

DispatcherServlet 调用视图解析器(ViewResolver)来解析 HandlerAdapter 传递的逻辑视图名。

视图解析器将解析的逻辑视图名传给 DispatcherServlet。

DispatcherServlet 根据视图解析器解析的视图结果,调用具体的视图。

最终视图呈现给用户。

Spring MVC 虽然整体流程复杂,但是实际开发中很简单,大部分的组件不需要开发者创建跟管理,只需要通过配置文件的方式完成配置即可,真正需要开发者进行处理的只有HandlerViewModle

但是随着前后端分离跟微服务的发展,一包走天下的开发模式其实用的不是很多了,大部分情况下是 SpringBoot + Vue

11. Spring Boot

11.1 Spring Boot简介

Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。Spring Boot 以约定大于配置核心思想开展工作,相比Spring具有如下优势:

Spring Boot 可以建立独立的Spring应用程序。

Spring Boot 内嵌了如Tomcat,Jetty和Undertow这样的容器,也就是说可以直接跑起来,用不着再做部署工作了。

Spring Boot 无需再像Spring那样搞一堆繁琐的xml文件的配置。

Spring Boot 可以自动配置(核心)Spring。SpringBoot将原有的XML配置改为Java配置,将bean注入改为使用注解注入的方式(@Autowire),并将多个xml、properties配置浓缩在一个appliaction.yml配置文件中。

Spring Boot 提供了一些现有的功能,如量度工具,表单数据验证以及一些外部配置这样的一些第三方功能。

Spring Boot 整合常用依赖(开发库,例如spring-webmvc、jackson-json、validation-api和tomcat等),提供的POM可以简化Maven的配置。当我们引入核心依赖时,SpringBoot会自引入其他依赖。

11.2 SpringBoot 注意点

  1. SpringBoot 抽离

将所有的功能场景都抽取出来,做成一个个的starter,spring-boot-starter-xxx 就是spring-boot的场景启动器。只需要在项目中引入这些starter即可,所有相关的依赖都会导入进来 。

  1. 自动配置原理

SpringBoot在启动的时候从类路径下的 META-INF/spring.factories 中获取 EnableAutoConfiguration 指定的值

我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类 xxxxAutoConfigurartion 当中。

我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件存在在其中,我们就不需要再手动配置了)。

给容器中自动配置类添加组件的时候,会从 xxxxProperties 类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可。

  1. 各种组件的整合

比如整合MyBatis、Redis、Swagger、Security、Shrio、Druid等,百度教程即可。

11.3 Springboot启动原理的底层

SpringApplication这个类主要做了以下四件事情:

推断应用的类型是普通的项目还是Web项目

查找并加载所有可用初始化器 , 设置到initializers属性中

找出所有的应用程序监听器,设置到listeners属性中

推断并设置main方法的定义类,找到运行的主类

SpringBoot启动大致流程如下(源网侵删):

面试官:关于Spring就问这13个点(下)

11.4 架构演进

)

  1. 单体应用

传统项目把所有的业务功能在一个项目中,这种单体架构结构逻辑比较简单,对于小型项目来说很实用。但随着业务量的增多,逻辑越来越复杂,项目会逐渐变得非常庞大,逻辑也会变得混乱,给维护和开发造成比较大的困难。

  1. 垂直架构

把原来比较大的单体项目根据业务逻辑拆分成多个小的单体项目,比如把物流系统、客户关系系统从原来的电子商城系统中抽离出来,构建成两个小的项目。这种架构虽然解决了原来单体项目过大的问题,但也带来了数据冗余、耦合性大的问题。

  1. SOA架构

面向服务架构(Service Oriented Architecture),它在垂直架构的基础上,把原来项目中的公共组件抽离出来做成形成服务,为各个系统提供服务。服务层即抽取出的公共组件。系统层的多个小型系统通过ESB企业服务总线(它是项目与服务之间通信的桥梁)以及Webservice调用服务,完成各自的业务逻辑。但是SOA架构抽取的粒度比较粗糙,系统与服务之间的耦合性很大,系统与服务界限不够清晰,给开发和维护造成一定的困难。

  1. 微服务架构

微服务架构对服务的抽取粒度更小,把系统中的服务层完全隔离出来。遵循单一原则,系统层和服务层的界限清晰,各个系统通过服务网关调用所需微服务。微服务之间通过RESTful等轻量级协议传输,相比ESB更轻量。但这种架构的开发成本比较高(因为新增了容错、分布式事务等要求),对团队的要求比较大,所以不适合小项目、小团队。

  1. 框架演变

从一个复杂应用场景衍生一种规范框架,用户只需要进行各种配置而不需要自己去实现它,这时候强大的配置功能成了优点。发展到一定程度之后,人们根据实际生产应用情况,选取其中实用功能和设计精华,重构出一些轻量级的框架。之后为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡约定大于配置的方案,进而衍生出一些一站式的解决方案。

12. Spring Cloud

)

微服务的定义 :

2014 年 Martin Fowler 提出的一种新的架构形式。微服务架构是一种架构模式,提倡将单一应用程序划分成一组小的服务,服务之间相互协调,互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务之间采用轻量级的通信机制(如HTTP或Dubbo)互相协作,每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境中,另外,应尽量避免统一的,集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具(如Maven)对其进行构建。

微服务化的核心就是将传统的一站式应用,根据业务拆分成一个一个的服务,彻底地去耦合,每一个微服务提供单个业务功能的服务,一个服务做一件事情,从技术角度看就是一种小而独立的处理过程,类似进程的概念,能够自行单独启动或销毁,拥有自己独立的数据库。

微服务时代核心问题(问题根本:网络不可靠):

服务很多,客户端怎么访问,如何提供对外网关?

这么多服务,服务之间如何通信? HTTP还是RPC?

这么多服务,如何治理? 服务的注册跟发现。

服务挂了怎么办?熔断机制。

主流微服务框架:

Spring Cloud Netflix

Spring Cloud Alibaba

Spring + Dubbo + ZooKeeper

关于 SpringCloud Netflix 前面详细写过,在此不再重复。

13. 常用注解

感觉Spring这块没啥特别好写的不知道为啥,可能跟自己用的少也有关吧,最后来几个简单注解收尾,一般有Spring核心注解、SpringBoot注解、SpringCloud注解、任务执行跟调度注解、测试注解、JPA注解、SpringMVC跟REST注解等等,这里只罗列下几个核心注解(全部注解公众号回复注解):

@Component : 可以配置CommandLineRunner使用,当一个组件不好归属到下面类的时候会用该注解标注,@Controller 、@Service、 @Repository 属于 Component的细化。

@Autowired :自动导入依赖的Bean,默认byType,完成属性,方法的组装,可以对类成员变量,方法,构造函数进行标注,加上(required=false)时找不到也不报错

@Import : 跟@Bean类似,更灵活的导入其他配置类。ImportSelector、ImportBeanDefinitionRegistrar等

@Bean : 等价xml中配置的bean, 用在方法上哦,来生产出一个bean,然后交给Spring管理

@Value : 可用在字段,构造器参数跟方法参数,指定一个默认值,支持 #{} 跟 ${} 两个方式。一般将SpringbBoot中的application.properties 配置的属性值赋值给变量。

@Configuration : 等价于Spring的XML配置文件,使用Java代码可以检查类型安全。如果有些时候必须用到xml配置文件,可通过@Configuration 类作为项目的配置主类,使用@ImportResource注解加载xml 文件

@Qualifier : 该注解通常跟@Autowired一起使用,当想对注入的过程做更多的控制,@Qualifier可帮助配置,比如两个以上相同类型的Bean时 Spring无法抉择,用到此注解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值