spring的定义
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。spring是非侵入性的,基于spring开发的应用一般不依赖于spring的类。
作为一个容器:它包含并且管理应用对象的生命周期和配置。如对象的创建,销毁,回调等。
作为一个框架:它提供一些基础功能(事务管理,持久层集成等),使开发人员跟专注于开发应用逻辑。(面向接口编程)
spring框架图
spring的IOC,DI,AOP
spring最核心的理念是IOC(控制反转)和AOP(面向切面编程),其中ioc是spring的基础,aop是spring的重要功能。
IOC(控制反转)
定义
官方的说法是:以前是由我们自己创建对象,包括依赖关系也是自己注入。使用了spring之后,对象的创建以及依赖关系可以由spring完成,反转控制就是反转了对象的创建方式,从我们自己创建反转给了程序创建(spring)
通俗的意思是:传统java开发模式中,当需要一个对象时,我们可以通过new/getInstance等啊直接或者间接调用构造方法创建一个对象。如果用了spring,spring容器使用了工厂模式为我们创建了所需要的对象,不用我们自己创建对象,只需要在配置文件中描述创建规则(哪些组件需要哪些服务),之后一个容器(ioc)负责把他们组装起来。之后我们直接调用spring提供的对象就可以了。
ioc容器初始化
DI(依赖注入)
定义:
我们将一系列的类交给spring管理,在需要的时候,不用自己定义,将需求提供给spring,之后spring会从它管理的组件中去查找,并使用javabean对象的set方法或者带参数的构造方法为其自动设置值。实现IOC思想需要DI做支持。
注入:
注入方式: 1.set方式注入 2.构造方法注入 3.字段注入
注入类型: 1.值类型注入 2.引用类型注入
构造器依赖注入:构造器依赖注入通过容器触发一个类的构造器来实现的,该类有一系列参数,每个参数代表一个对其他类的依赖。
Setter方法注入:Setter方法注入是容器通过调用无参构造器或无参static工厂 方法实例化bean之后,调用该bean的setter方法,即实现了基于setter的依赖注入。
基于特定接口:(侵入式方案)
AOP(面向切面编程)
定义:
官方:在面向对象编程(oop)思想中,我们将事物纵向抽成一个个对象,而在面向切面编程的时候,我们将一个个的对象某些类似的方面横向抽成一个切面,对这个切面进行一些如权限控制,事务管理,记录日志等公用操作处理的过程就是面向切面编程的思想,aop底层是动态代理,如果是接口采用jdk动态代理,如果是类采用cglib方式实现动态代理。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
通俗:用刀切水果,切开的口子就是切面。编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。
一些概念:
切面(Aspect):切入业务流程的一个独立模块。例如,前面案例的VerifyUser类,一个应用程序可以拥有任意数量的切面。
连接点(Join point):也就是业务流程在运行过程中需要插入切面的具体位置。
增强/通知(Advice):是切面的具体实现方法。可分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)和环绕通知(Around)五种。实现方法具体属于哪类通知,是在配置文件和注解中指定的。
切点(Pointcut):用于定义通知应该切入到哪些连接点上,不同的通知通常需要切入到不同的连接点上。
目标对象(Target):被一个或者多个切面所通知的对象。
代理对象(Proxy):表示代理对象。将通知应用到目标对象之后被动态创建的对象。可以简单地理解为,代理对象为目标对象的业务逻辑功能加上被切入的切面所形成的对象。
织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程。这个过程可以发生在编译期、类装载期及运行期。
spring的优点
1. 非侵入式
spring是一种非侵入式框架,它可以使应用程序的代码对框架的依赖最小化。
2. 简化开发,方便解耦
所有对象的创建以及依赖关系的维护都交给spring容器去管理,降低组件之间的耦合性。
3. 支持声明式事务管理
只需要通过配置就可以完成对事物的管理,而无须手动编程。
4. 测试方便
支持Junit4,可以通过注解来测试程序。
5. 方便集成各种优秀框架
spring对一些优秀框架完美支持(struts,hibernate,mybatis,quartz)
6. 降低Jave EE API的使用难度。
Spring对Java EE开发中非常难用的一些API(如JDBC、JavaMail等),都提供了封装,使这些API应用难度大大降低。
spring中的设计模式
1. 单例模式:Spring 中的 Bean 默认都是单例的。
2. 工厂模式:spring使用工厂模式通过BeanFactory,ApplicationContext创建bean对象。(在工厂模式中,我们在创建对象的时候不会对客户端暴漏创建逻辑,并且是只通过使用同一个接口来指向新创建的对象)
3. 控制反转/依赖注入:上面有具体描述
4. 代理模式:springAop功能的实现。
5. 模板方式模式:用来解决重复代码的问题。(比如:RestTemplate,JmsTemplate,JpaTemplate).
6. 前端控制器模式:spring提供了前端控制器dispacherServlet来对请求进行分发。
spring bean的生命周期
1. bean定义:在配置文件里面使用<bean></bean>来定义。
2. bean初始化:(三种可以搭配使用,顺序为3,2,1)
(1)配置文件中通过init-method属性来执行指定的初始化方法。或者
注解的方式。(2)实现InitializingBean接口。主要是afterPropertiesSet()方法。
(3)方法上使用@PostConstruct注解。
3. bean调用:这个不用多说。
4. bean销毁:配置文件中通过destroy-method属性来执行指定的销毁方法。
spring的事务
首先要说对事务的理解:
这里举个例子,比如我用银行卡转钱到微信,正确的情况应该是微信的钱多了,银行卡的钱少了,那么如果这个过程中出现了银行卡里的钱减少了,但是微信里的钱没增加,肯定是不合理的,那么如何应对或者说防止这种事呢,我们可以将这两个动作同时执行,如果其中一个失败了,那么另一个就回滚,只有都成功的情况下,才一起提交,事务就是用来解决这个问题的。
事务的四大特性:(ACID)
1. 原子性(Atomicity):事务是由一系列动作组成,原子性就是保证这些动作要么全部成功,要么都不起作用。
2. 一致性(Consistency):一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。拿转账举例子,转帐前两个账户的总金额是100,那么转账之后总金额还要是100。
3. 隔离性(Isolation):是当多个用户同一时刻访问数据库的同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
4. 持久性(Durability):是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
事务中的隔离级别:
1. Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
2. Repeatable read (可重复读):可避免脏读、不可重复读的发生。
3. Read committed (读已提交):可避免脏读的发生。
4. Read uncommitted (读未提交):最低级别,任何情况都无法保证。
Serializable级别最高,Read uncommitted级别最低,级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在MySQL数据库中默认的隔离级别为Repeatable read (可重复读)。
在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);
而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。
脏读,不可重复读,幻读:
脏读:脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
例:当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。
不可重复读:不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
虚读(幻读):幻读是事务非独立执行时发生的一种现象。
例:例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)
Spring学习线路
参考:
https://www.cnblogs.com/fjdingsd/p/5273008.html
https://www.cnblogs.com/qq-2374314442/p/8530888.html
持续更新!!!