《深入浅出Sprint Boot 2.X》笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011311291/article/details/84993262

Spring的核心概念
1.控制反转(Inversion of Control,IOC)
2.面向切面编程(Aspect Oriented Programming,AOP)

IOC
IOC是通过描述来生成或者获取对象的技术,很多java初学者更多的时候所熟悉的是使用new关键字来创建对象
而在Spring中,它是通过描述来创建对象

Spring Bean
Spring把每一个需要管理的对象称为Spring Bean.而关系这些Bean的容器,被我们称为Spring IOC容器

Spring IOC 容器
是一个管理Spring Bean的容器,其中Spring IOC容器具备两个基本功能
1.通过描述管理Bean,包括发布和获取Bean
2.通过描述完成Bean之间的依赖关系
所有的IOC容器都需要实现接口BeanFactory,包括目前最常用的接口ApplicationContext
目前常用的容器 AnnotationConfigApplicationContext
注意:
1.Spring IOC容器默认下 Bean都是以单例的形式存在

和Spring IOC容器相关的注解
1.@Configuration 一般放在类上,使用在config包中,代表这是一个java配置文件,Spring的容器会根据它来生成IOC容器去装配Bean
2.@Bean 一般放在方法上和1搭配使用,定义生成的是一个Bean
如果每个方法都需要一个个@Bean去注解,这很麻烦,所以有
3.@Component 表名哪个类被扫描进入Spring IOC容器,一般使用才domain类中
4.@ComponentScan 表名采用何种策略去扫描装配Bean,一般使用在config包中

Spring IOC Bean之间的依赖关系,依赖注入(Dependency Injection,DI)
相关注解
1.@Autowired 它会根据属性的类型找到对应的Bean进行注入,重点在于根据属性的类型,会导致冲突
比如有接口Animal,实现类有猫有狗,调用时有
@Autowired
private Animal animal = null
这样使用会发生错误,不知道Animal应该获取的是猫还是狗,而应该使用:
1.当发现有两个实现类的时候,就会根据名称获取实现类
@Autowired
private Animal dog = null
2.使用@Primary注解,表示优先获取该实例
3.或者使用@Qualifier(“dog”)

Spring Bean的生命周期

读取application.properties用到的注解
1.@Value 例如@Value("${database.driverName}"),一般放在变量或者方法上,读取配置文件中的值给变量赋值
2.@ConfigurationProperties 例如@ConfigurationProperties(“database”),自动给类中 一般放在类上,读取配置文件,给相应的变量赋值
3.@PropertySource 用于引用自定义配置属性文件,例如@PropertySource(value={“classpath:jdbc.properties”},ignoreResourceNotFound=true)

Spring Bean的作用域
1.singleton 使用范围:所有Spring应用 默认值,IOC容器只存在单例
2.prototype 使用范围:所有Spring应用 每当从IOC容器中取出一个Bean,则创建一个新的Bean
3.session 使用范围:所有Web应用 HTTP会话
4.application 使用范围:所有Web应用 Web工程生命周期
5.request 使用范围:所有Web应用 Web工程单次请求(request)
6.globalSession 使用范围:所有Web应用 在一个全局的HTTP Session中,一个Bean定义对应一个实例,实践中基本不会用
@Scope 可以使用此注解生命作用域,例如(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

使用XML配置Bean
@importResource

Spring Boot 还提供了Spring EL表达式
例如给某个变量附上时间
@Value("#{T(System).currentTimeMillis()}")

Spring AOP
其实是一种约定编程,相当于动态代理
为什么要使用AOP?
1.减少重复开发,可以让开发者聚焦于主要功能
比方说存储一个用户信息到数据库,按照JDBC的步骤
获取数据库连接->执行SQL->是否发生异常->是则回滚是否,否则提交事务->释放数据库连接
如果采用了AOP
则只需要关注 执行SQL 这一步骤,其它都交给代理完成

AOP重要的几个概念
1.连接点(join point) 对应的是具备被拦截的对象(也就是要代理的方法)
2.切点(point cut) 有时候切面不单单应用于单个方法,也可能是多个类不同的方法,这时候可以通过正则式和指示器的规则去定义,从而适配连接点,切点就是提供这样一个功能的概念
3.通知(advice) 按照约定的流程,分为
前置通知(before advice)
后置通知(after advice)
环绕通知(around advice)
事后返回通知(afterReturning advice)
异常通知(afterThrowing advice)
4.目标对象(taget) 被代理的对象
5.引入(intoduction) 对某方法引入新的类和方法,增强现有Bean的功能
6.织入(weaving) 它是一个通过动态代理技术,为原有对象生成代理对象,然后将与切点定义匹配的连接点拦截,并按约定将各类通知织入约定流程的过程
7.切面(aspect) 是一个可以定义切点,各类通知和引入的内容,Spring AOP将通过它的信息来增强Bean的功能或者将对应的方法织入流程
用到的注解
1.@aspect 定义切面
2.@before 定义通知
3.@After
4.@Around
5.@AfterReturning
6.@AfterThrowing
7.@Pointcut 定义切点
8.DeclareParents 用于引入
9.@Order 在使用多切面的时候可以指定切面顺序

Spring 的声明式事务使用
@Transactional
可以标注在方法和类上,当标注在类上时,代表这个类的所有公共非静态方法都将启用事务功能
其中隔离级别(isolation)和传播行为(propagation)是主要内容

隔离级别(isolation)
数据库事务具有以下4个基本特征,也就是注明的ACID,原子性(Atomic),一致性(Consistency),隔离性(Isolation),持久性(Durability)这4个除了隔离性都比较好理解。
隔离性,因为互联网应用时刻面对着高并发的环境,如商品库存,时刻都是多个线程共享的数据,这样就会在多线程
的环境中扣减商品库存,就会出现多个事务同时访问同一记录的情况,引起数据不一致的状况。为了提供性能,减少锁付出的代价,隔离是一种好方法。
引发数据不一致情况分为几类:
1.第一类丢失更新
一个事物回滚另外一个事物提交而引起数据不一致
2.第二类丢失更新
多个事物并发都提交引发数据不一致

对于第一类现在的数据库基本没有什么问题,对于第二类数据库提出了4重隔离级别
1.未提交读(Read uncommitted)
是最低的隔离级别,其含义是允许一个事物读取另外一个事务没有提交的数据,是一种危险的隔离级别
2.读写提交(Read committed)
指一个事务只能读取另外一个事务已经提交的数据,不能读取未提交的数据,还是会出现危险。
比如:
图片
对于事务2而言,之前认为可以扣减,但到了扣减那一步却发现已经不可以扣减,所以库存对于事务2是一个
可变化的值,这样的现在称为不可重复读问题。
3.可重复读(Repeatable read)
为了克服上述不可重复读问题,提出了可重复读隔离级别。也就是在事务1未提交前(修改),事务2不允许读取。
但是这样的方式会出现幻读,如图

4.串行化(Serializable)
串行化是数据库隔离级别的最高级别,它会要求所有Sql都会按照顺序执行,可以克服上述隔离界别出现的各种问题。

不是所有数据库都支持4种隔离级别的,比如Oracle只支持读写提交和串行化,而mysql支持可以支持4种,默认为REPEATABLE-READ。

Spring事务传播行为:
传播行为是方法之间调用事务采取的策略问题,策略:
1.要么全部成功,要么全部回退
2.成功的提交,失败的回滚

Spring事务机制中有7种传播行为,但是常用的基本上只有这3种:
1.REQUIRED 默认的传播行为,如果当前(最初始调用事务的方法)存在事务,就沿用当前事务,否则新建一个事务运行子方法
2.REQUIRED_NEW 无论当前事务是否存在,都会创建新事务运行方法,这样新事务就可以拥有新的锁和隔离级别等新特性,与当前事务相互独立
3.NESTED 在当前方法调用子方法时,如果子方法发生异常,只回滚子方法执行过的SQL,而不回滚当前方法中的事务
其实异常回滚还是使用保存点。
NESTED和REQUIRED_NEW的区别:
NESTED传播行为会沿用当前事务的隔离级别和锁等特性,而REQUIRED_NEW拥有自己独立的隔离级别和锁等特性

Sping 其他技术
1.异步线程池,Spring中存在AsyncConfigurer接口
2.异步消息,JMS java消息服务(Java Message Service),比如短信系统,验证码登录等,短信系统因为繁忙而没有很快的将短信发出。
JMS 按照规范分为点对点(Point-to-Point)和发布订阅(Publish/Subscribe)两种形式
点对点:
就是将一个系统的消息分布到指定的另外一个系统,这样另外一个系统就能获得消息,从而处理对应的业务逻辑
发布订阅模式:
是一个系统约定将消息发布到一个主题(Topic)中,然后各个系统就能狗通过订阅这个主题,根据发送过来的消息处理对应的业务。
JMS服务的规范有很多,比如常见的传统的ActiveMQ和分布式的Kafka。为了更可靠和安全,还存在AMQP协议,实现它比较常用的有RabbitMQ。
3.定时器 在Spring中使用定时器比较简单,在配置文件中加入@EnableScheduling,然后通过@Scheduled去配置如何定时。
4.WebSocket应用 WebSocket协议是基于TCP的一种新的网络协议,它实现浏览器和服务器全双工通信,允许服务器主动发送信息给客户端,这样就可以
从客户端发送消息到服务器,有些浏览器支持WebSocket协议,有些不支持,可以使用STOMP协议来进行兼容。

Spring5 WebFlux
游戏,视频,新闻,和广告的网站,他们一般不会涉及账户和财产问题,也就是不需要很高的数据一致性,但是对于并发数和响应速度却十分在意
而使用传统的开发模式会引入一致性的机制,这是造成他们性能瓶颈的原因之一,为此提出了响应式变成理念。WebFlux就是一种响应式框架。
1.传统编程中的模型:
请求->请求队列->分发器->处理线程
缺点:当处理线程不能及时响应用户时,大量的线程只能在请求队列中等待或者被抛弃。
2.响应式模型
(1)客户端订阅事件(此时还不是请求)
(2)Selector线程,轮询客户端发过来的事件,并不处理请求,找到对应的请求处理器,然后开启另外一条线程处理
由于事件存在很多种,所以处理器也存在多个。
响应式编程分为RouterFuncations,Spring WebFlux,HTTP/Reactive Stream三层
(1)RouterFuncations是一个路由分发层,根据请求的事件,决定采用什么类的什么方法处理处理客户端发送过来的请求,它就是selector的作用
(2)Spring-webflux是控制层,只要处理业务逻辑前进行封装的封装和控制数据流返回格式
(3)HTTP/Reactive Stream是将结果转换为数据流的过程。

对于数据流的封装,Reactor响应式模式提供Flux和Mono
(1)Flux存放0-N个数据流序列,响应式框架会一个接一个的将它们发送到客户端
(2)Mono存放0-1个数据流序列。
这里还有一个背拉的概念,这个概念只对Flux有意义:
对于客户端,有时候响应能力距离服务端有很大差距,如果在很短的时间内个客户端传输给客户端,有可能
客户端会被压垮,为了处理这个问题,可以使用响应式拉取,将服务器端的数据流划分多个序列,一次仅发送一个数据流
序列给客户端,当客户端处理完这个序列后再给服务器发送消息,然后再拉取第二个序列,直到Flux中的0-N个数据流被完全处理。

Spring WebFlux 还提供了比RestTemplate更为强大的类WebClient,可以使用Flux,Mono等

高并发开发:
解决商品在高并发下超发问题:
1.悲观锁,就是加锁以后其它不能去修改,容易造成抢锁和积压
2.乐观锁,带版本号更新,我在修改数据前先获取一个版本号,然后在修改的时候查看当前版本号是否符合,如果是则处理,如果不是则直接返回,优点不会造成用户积压,缺点就是代码比较多,且会出现较多请求失败,需要重新请求或者丢弃
3.使用redis处理高并发,利用readis内存性能,和原子性,再定时刷新到数据库

猜你喜欢

转载自blog.csdn.net/u011311291/article/details/84993262