IOC(控制反转)
IOC是一种设计思想,而不是什么技术
传统方法我们是在对象内部通过new进行对象创建,由程序主动去创建依赖对象。就是由我们自己去进行对象的创建,销毁过程
IOC则是不再自己负责依赖对象的创建和销毁,而是由Spring容器来控制对象生命周期
通俗点讲
IOC就是手机需要充电时,你给它充电,你就是IOC容器,因为手机和充电器控制权都在你手里。
DI(依赖注入)
DI说的是创建对象实例时,为这个对象注入属性值或其他对象实例
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
●谁依赖于谁:应用程序依赖于IOC容器;
●为什么需要依赖:应用程序需要IOC容器来提供对象需要的外部资源;
●谁注入谁:IOC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
AOP(面向切面编程)
我理解的AOP就是在不破坏代码的情况下进行事务,日志,权限等操作
AOP代理是离不开Spring的IOC容器,代理的生成,管理及其依赖关系都是由IOC容器负责,Spring默认使用JDK动态代理,在需要代理类而不是代理接口的时候,Spring会自动切换为使用CGLIB代理
JDK动态代理:基于接口实现代理
CGLIB动态代理:基于Class类实现代理
关于更多动态代理理解可访问 https://blog.csdn.net/flyfeifei66/article/details/81481222
AOP就是你手机充电前/后你想玩个小游戏,你玩小游戏这个动作就是在不破坏充电的情况下完成的。
AOP基本术语
1.通知(Advice)
就是你想要的功能,也就是上面说的 安全,事物,日志等。你给先定义好把,然后在想用的地方用一下。
2.连接点(JoinPoint)
这个更好解释了,就是spring允许你使用通知的地方,那可真就多了,基本每个方法的前,后(两者都有也行),或抛出异常时都可以是连接点,spring只支持方法连接点.其他如aspectJ还可以让你在构造器或属性注入时都行,不过那不是咱关注的,只要记住,和方法有关的前前后后(抛出异常),都是连接点。
3.切入点(Pointcut)
上面说的连接点的基础上,来定义切入点,你的一个类里,有15个方法,那就有几十个连接点了对把,但是你并不想在所有方法附近都使用通知(使用叫织入,以后再说),你只想让其中的几个,在调用这几个方法之前,之后或者抛出异常时干点什么,那么就用切点来定义这几个方法,让切点来筛选连接点,选中那几个你想要的方法。
4.切面(Aspect)
切面是通知和切入点的结合。现在发现了吧,没连接点什么事情,连接点就是为了让你好理解切点,搞出来的,明白这个概念就行了。通知说明了干什么和什么时候干(什么时候通过方法名中的before,after,around等就能知道),而切入点说明了在哪干(指定到底是哪个方法),这就是一个完整的切面定义。
5.引入(introduction)
允许我们向现有的类添加新方法属性。这不就是把切面(也就是新方法属性:通知定义的)用到目标类中吗
6.目标(target)
引入中所提到的目标类,也就是要被通知的对象,也就是真正的业务逻辑,他可以在毫不知情的情况下,被咱们织入切面。而自己专注于业务本身的逻辑。
7.代理(proxy)
怎么实现整套aop机制的,都是通过代理,这个一会给细说。
8.织入(weaving)
把切面应用到目标对象来创建新的代理对象的过程。有3种方式,spring采用的是运行时,为什么是运行时,后面解释。
关键就是:切点定义了哪些连接点会得到通知
Spring事务
事务具备四种特性 ACID 那么什么是ACID呢
原子性(Atomicity)
事务原子性指的是要么全部成功,要么全部失败,不会结束在中间某个环节。如果事务在执行过程中出现异常,则会回滚到事务开始前的状态。
一致性(Consistency)
事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。
举个栗子
友人A余额:100
友人B余额:0
友人A给友人B转账 不管转账几次 友人A跟友人B的余额总数加起来都是100 ---------不会出现多了或少了的情况。
隔离性(Isolation)
事务的隔离性指的是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间互不干扰。事务查看数据更新时,数据状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
持久性(Durability)
事务的持久性指的是当事务成功提交时那么对数据库中的数据的改变就是永久性的。即便数据库系统发生系统崩溃,重启数据库系统后,数据库依然是事务成功结束时的状态。
事务传播特性
事务传播行为就是多个事务方法调用时,如何定义方法间事务的传播。Spring定义了7种传播行为:
- propagation_required 如果当前没有事务就新建一个事务,如果存在事务则加入到这个事务中
- propagation_required_new 新建事务,如果当前有事务则将当前事务挂起
- propagation_supports 支持当前事务,如果没有当前事务则以无事务方法执行
- propagation_not_supported 以非事务方式执行操作,如果当前存在事务,就将当前事务挂起。
- propagation_mandatory 使用当前事务,如果没有当前事务,就抛出异常。
- propagation_never 以非事务方式执行操作,如果存在当前事务则抛出异常。
- propagation_nested
(1) 如果当前存在事务,它将会成为父级的一个子事务,方法结束后并没有提交,只是等待父事务结束才提交。
(2) 如果当前没有事务,则执行与propagation_required类似的操作。
(3) 如果子事务本身异常,父级可以捕获到它的异常,而不进行回滚。正常提交。
脏读,不可重复读,幻读
首先说明下事务并发会引发三种情况
脏读
读到了别的事务回滚前的数据。
举个栗子
事务B执行过程中修改了数据X,在未提交前,事务A读取了X,而事务B却回滚了,这样事务A就形成了脏读。
不可重复读
指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事务内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。
举个栗子
A事务首先读取了一条数据,然后执行逻辑的时候,B事务将这条数据改变了,然后A事务再次读取的时发现数据不匹配了,就是所谓的不可重复读。
幻读
A事务读取记录时B事务增加了记录并提交,A事务再次读取时可以看到B事务新增的记录
举个栗子
A事务首先根据条件索引得到10条数据,然后B事务改变了数据库一条数据,导致也符合A事务当时的搜索条件,这样A事务再次搜索发现有11条数据了,就产生了幻读。
事务隔离级别
事务隔离级别指的是一个事务对数据的修改与另一个并行的事务的隔离程度,当多个事务同时访问相同数据时,如果没有采取必要的隔离机制,就可能发生 脏读,不可重复读,幻读
隔离级别
DEFAULT(默认)
使用数据库本身使用的隔离级别
ORACLE(读已提交) MySQL(可重复读)
READ_COMMITTED (读已提交)
ORACLE默认隔离级别
保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻读。
REPEATABLE_READ (可重复读)
InnoDB默认级别(MySQL的数据库引擎之一)
这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻读(InnoDB解决了幻读)。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。
READ_UNCOMMITTED (读未提交)
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻读。
SERIALIZABLE(串行化)
高代价但是最可靠的最高的事务隔离级别,每次读都需要获得表级共享锁,读写相互都会阻塞,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了