1.简介
- 2002年首次推出了Spring框架的雏形:interface21框架!
- Spring理念:使现有技术更加容易使用,本身是一个大杂烩,整合了现有的所有框架技术!
- SSH:Struct2+Spring+Hibernate
- SSM:SpringMvc+Spring+Mybatis
- 导包:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.22</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.22</version>
</dependency>
1.1 Spring 的优点
- Spring 是一个开源的、免费的框架(容器)。
- Spring是一个轻量级的、非入侵式的框架。
- 控制反转(IOC)。
- 面向切面编程(AOP)。
- 支持事务的处理,对框架整合的支持。
- 非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API
- 依赖注入:DI——Dependency Injection,反转控制(IOC)最经典的实现
- 面向切面编程:Aspect Oriented Programming——AOP
- 容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期
- 组件化:Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象
- 一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的Spring JDBC)
总结:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!
1.2 Spring的组成
1.3 拓展
Spring官网介绍:现代化的Java开发!
- Spring Boot
- 一个快速开发的脚手架。
- 基于Spring Boot可以快速开发单个的微服务。
- 约定大于配置。
- Spring Cloud
- Spring Cloud是基于Spring Boot实现的。
因为大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!承上启下的作用。
1.3.1 Spring的弊端
发展太久之后,违背了原来的理念!配置十分繁琐。
1.4 IOC理论推导
1.4.1 原先业务步骤:
- UserDao:接口
- UserDaoImpl:实现类
- UserService:业务接口
- UserServiceImpl:业务实现类
1.4.2 Ioc
IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置使用IoC。
Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从IoC容易中取出需要的对象。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency Injection,Dl)。jinshnsa
这个过程就叫控制反转∶
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.
反转∶程序本身不创建对象,而变成被动的接收对象.依赖注入:就是利用set方法来进行注入的.
IOC是一种编程思想,由主动的编程变成被动的接收.
2.各类注解
2.1 @Autowired
Autowired是根据类型进行自动装配的,如果出现重复的会报错,@Qualifier配合@Autowired来解决这些问题。例如:
@Autowired
@Qualifier("userServiceImpl")
基本面试也常问两者的区别:
Autowired按byType自动注入,Resource默认按 byName自动注入
@Autowired//默认按type注入
@Qualifier(“cusInfoService”)//一般作为@Autowired()的修饰用
@Resource(name=“userService”)//默认按name注入,可以通过name和
type属性进行选择性注入
简单理解:
@Autowired 根据类型注入,
@Resource 默认根据名字注入,其次按照类型搜索
@Autowired @Qualifie(“userService”) 两个结合起来可以根据名字和类型注入
2.2 @Rerource:
有两个属性是比较重要的,分是name和type;name属性解析为bean的名字,而type属性则解析为bean的类型。
@Resource装配顺序:
1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配;
3.Spring的事务类型:
3.1Spring的七种传播行为:
1.PROPAGATION_REQUIRED – 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
2.PROPAGATION_SUPPORTS – 支持当前事务,如果当前没有事务,就以非事务方式执行。
3.PROPAGATION_MANDATORY – 支持当前事务,如果当前没有事务,就抛出异常。
4.PROPAGATION_REQUIRES_NEW – 新建事务,如果当前存在事务,把当前事务挂起。
5.PROPAGATION_NOT_SUPPORTED – 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6.PROPAGATION_NEVER – 以非事务方式执行,如果当前存在事务,则抛出异常。
7.PROPAGATION_NESTED – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,
例如:
//指定了rollbackFor =Exception.class,表示报任何错都回归
@Transactional(propagation = Propagation.REQUIRED,rollbackFor =Exception.class)
3.2五种隔离级别:
1.ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.另外四个与JDBC的隔离级别相对应;
2.ISOLATION_READ_UNCOMMITTED 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
3.ISOLATION_READ_COMMITTED 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
4.ISOLATION_REPEATABLE_READ 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
5.ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
@Transactional(propagation = Propagation.REQUIRED,rollbackFor =Exception.class,isolation= Isolation.DEFAULT )
4.耦合和内聚
4.1 耦合性
也称耦合度,是对模块间关联程度的度量。
- 在软件工程中,耦合指的就是对象之间的依赖性,对象之间的耦合度越高,维护成本就越高,因此对象的设计应使类和构件之间的耦合最小。
- 软件设计中通常用耦合度和内聚度来衡量模块独立程序的标准。
- 划分模块的一个准则就是高内聚低耦合
- 内聚:标志一个模块内各个元素彼此结合的紧密程度,它是信息隐蔽和局部化概念的自然扩展。
- 内聚是从功能角度来度量模块内的联系,一个好的内聚模块应当恰好做一件事
- 内聚和耦合是密切相关的,同其他模块存在高耦合的模块意味着低内聚,而高内聚的模块意味着该模块同其它模块之间是低耦合
- 在进行软件设计使,应做到高内聚、低耦合
5.IoC 控制反转
5.1 什么是IoC?
IoC,全称Inversion of Control,即控制反转。IoC并不是某一具体的技术,而是一种设计思想,Spring IoC框架/容器就是IoC这一思想的具体实现。
IoC的核心思想在于,资源不由使用资源的双方管理,交由不使用资源的第三方管理。在通常情况下,当我们需要使用或依赖某一个类或服务,我们通常会使用new关键字等方法直接地主动地创建对象。而在IoC的思想下,创建对象这部分工作被委托给了IoC容器,即将此工作的控制权交由IoC容器,控制反转。图示如下:
以Spring IoC容器为例,它负责创建对象、自动装配对象、配置对象,并管理这些对象(bean)的生命周期。
引用《Spring揭秘》中的一句话概括IoC:“IoC是一种可以帮助我们解耦各业务对象间依赖关系的对象绑定方式!”
5.2 IoC的两种实现方式:
IoC这一思想的具体实现由两种方式,分别为:依赖注入(DI,Dependency Injection)、依赖查找(DL,Dependency Lookup)。
5.2.1 什么是依赖?
依赖,即Dependency,是非常常见的概念,简单举例说明,假设现有两个类A和B,如果在A类中引用了B类,即有B类型字段在A类中,就可以说A类依赖于B类,B类是A类的依赖。
5.2.2 依赖注入:
此实现方法指某对象的依赖通过注入的方式进行创建,由容器动态将依赖关系中的目标对象实例注入到各组件中,对象实例的创建配置等工作均由容器完成实现。
依赖注入对代码的侵入性较小,即硬编码部分不多,可以很好的提升代码的重用率,更加灵活易扩展,实现本身不需要依赖过多容器的API,耦合度较小。
依赖注入有三种方式,分别是接口注入、构造方法注入和setter注入,其中接口注入由于其代码侵入性过高,已鲜有使用。在Spring中,诸如@Autowired和@Resource等注解就是依赖注入的体现。
5.2.3依赖查找:
依赖查找是一种十分传统的IoC实现方式,即容器中的对象通过容器的API来查找该对象所依赖的资源,此种方式相较依赖注入,更多的依赖了容器的API,即用户需要自己手动地主动地使用容器的API去查找资源组装对象。
依赖查找也有两种方式,分别是依赖拖拽和上下文依赖查找。
————————————————
阅读过依赖注入和依赖查找的简述,想必读者都能分清哪种实现方式更能体现IoC的思想,更不背离IoC思想的初衷,答案当然是依赖注入,依赖查找这种方式因侵入性高,且需要开发人员主动调用容器API,在实践中鲜有人使用,可以大概认定为已被弃用。
而依赖注入因其是IoC框架的核心实现,且十分符合IoC的思想,也有人认为控制反转和依赖注入是同一种概念,此处见仁见智。
IoC与依赖查找及依赖注入关系图如下:
5.2.4 使用IoC的优缺点:
优点:
- 解耦。由于引入了第三方资源管理者,降低了资源使用双方的耦合度。
- 资源集中管理。使得资源可配置易管理。
缺点:
- 创建对象的过程没有使用new关键字创建直观,相较复杂。
- Java中IoC使用反射创建对象,效率没有直接创建高。
- 使用非基于注解的IoC,即基于配置文件的方式需要手动配置。
6.AOP面向切面编程
6.1 什么是AOP?
6.1.1 官方解释:
通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
6.1.2 我的理解:
A,B,C三个方法,但是在调用每一个方法之前,要求打印一个日志:某一个方法被开始调用了!
在调用每个方法之后,也要求打印日志:某个方法被调用完了!
一般人会在每一个方法的开始和结尾部分都会添加一句日志打印吧,这样做如果方法多了,就会有很多重复的代码,显得很麻烦,这时候有人会想到,为什么不把打印日志这个功能封装一下,然后让它能在指定的地方(比如执行方法前,或者执行方法后)自动的去调用呢?如果可以的话,业务功能代码中就不会掺杂这一下其他的代码,所以AOP就是做了这一类的工作,比如,日志输出,事务控制,异常的处理等。
6.2 AOP的优点:
- 降低了代码的耦合度
- 提高了代码的重用性,减轻了程序员的工作量
- 系统更加容易扩展
6.3 AOP编程术语
- 切面(Aspect)
给业务方法增加的功能
- 连接点(JoinPoint)
连接切面的业务方法,这个方法执行时,会执行切面的功能。
- 切入点(Pointcut)
指声明的一个或多个连接点的集合。通过切入点指定一组方法,这些方法执行时,都能增加切面的功能。被标记为 final 的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。
- 目标对象(Target)
指将要被增强的对象,即包含主业务逻辑的类的对象。
- 通知(Advice)
表示切面的执行时间,通知定义了增江代码切入到目标代码的时间点,是木匾方法执行之前执行,还是之后执行等
6.4 使用Aspectj框架实现AOP
6.4.1 常用的通知五种类型
- @Before:前置通知
- @AfterReturnring:后置通知
- @Around:环绕通知
- @AfterThrowing:异常通知
- @Ater:最终通知
6.4.2 AspectJ的切入点表达式
execution(modifiers-pattern?
ret-type-pattern
declaring-type-pattern?
name-pattern(param-pattern)
throws-pattern?)
- modifiers-pattern] 访问权限类型
- ret-type-pattern 返回值类型
- declaring-type-pattern 包名类名
- name-pattern(param-pattern) 方法名(参数类型和参数个数)
- throws-pattern 抛出异常类型
- ?表示可选的部分