spring入门教程(spring基础教程)

spring入门教程(spring基础教程)svg xmlns http www w3 org 2000 svg style display none svg

大家好,我是讯享网,很高兴认识大家。



 <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path> </svg> <p></p> 

讯享网

Spring 基础框架,可以视为Spring 基础设施,基本上任何其他 Spring 项目都是以 SpringFramework 为基础的。

在这里插入图片描述
讯享网

Spring 5 的模块结构图:
在这里插入图片描述

在这里插入图片描述

lOC: Inversion of Control,翻译过来是反转控制。把对象创建和对象之间的调用过程,交给 Spring 进行管理

在这里插入图片描述

Spring 的IOC 容器就是IOC 思想的一个落地的产品实现。IOC 容器中管理的组件也叫做 bean。在创建 bean 之前,首先需要创建IOC容器。

Spring 提供了IOC容器的两种实现方式:
在这里插入图片描述
(1) BeanFactory:IOC容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用
加载配置文件时候不会创建对象,只有在使用(获取)对象的时候才会创建

(2) ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用,加载配置文件时候就会把配置文件中的对象进行创建

在这里插入图片描述
在这里插入图片描述

IOC底层原理:xml解析、工厂模式、反射

在这里插入图片描述
在这里插入图片描述

3.1 引入依赖

讯享网

3.2 创建类

 

3.3 创建Spring的配置文件

讯享网

3.4 创建测试类

 

3.5 总结

获取bean的三种方式:
* 1、根bean的id获取
* 2、根bean的类型获取
* 注意:根据类型获取bean时,要求IOC容器中有且只有一个类型匹配的bean
* 若没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException
* 若有多个类型匹配的bean,此时抛出异常:NoUniqueBeanDefinitionException
* 3、根据bean的id和类型获取
* 结论:根据类型来获取bean时,在满足bean唯一性的前提下其实只是看:[对象 instanceof 指定的类型]的返回结果只要返回的是true就可以认定为和类型匹配,能够获取到。
* 即通过bean的类型、bean所继承的类的类型、bean所实现的接口的类型都可以获取bean
在这里插入图片描述

4.1 setter注入

Spring配置文件

讯享网

测试方法:

 

4.2 构造器注入

Spring配置文件

讯享网

测试方法:

 

4.3 特殊值赋值

  • 字面量赋值

什么是字面量?
int a = 10:
声明一个变量a,初始化为10,此时a就不代表字母a了,而是作为一个变量的名字。当我们引用a的时候,我们实际上拿到的值是10。
而如果a是带引号的:‘a’,那么它现在不是一个变量,它就是代表a这个字母本身,这就是字面量。所以字面最没有引申含义,就是我们看到的这个数据本身。

讯享网
  • null值
 
  • xml实体

在这里插入图片描述

  • CDATA节:其中的内容会原样解析

在这里插入图片描述
CDATA节是xml中一个特殊的标签,因此不能写在一个属性中。

讯享网

测试结果:
在这里插入图片描述

  • 类类型的属性赋值

1.引用外部的Bean的id

 

在这里插入图片描述
2.通过级联方式赋值

讯享网

在这里插入图片描述
3. 内部bean

 

在这里插入图片描述

  • 数值类型属性赋值
讯享网

测试方法:

 

在这里插入图片描述

  • list集合类型属性赋值

1.级联赋值

讯享网

测试方法:

 

在这里插入图片描述

2.引用赋值(需要用到util命名空间)

讯享网
  • map集合属性赋值

1.级联赋值

 

测试方法:

讯享网

在这里插入图片描述

2.引用赋值

 
  • p命名空间

引入约束

讯享网

测试方法:

 

在这里插入图片描述

  • 管理数据源和引入外部属性文件

引入依赖

讯享网

配置spring配置文件

 

或者:引入properties配置文件,需添加context约束

讯享网

测试方法:

 

在这里插入图片描述

5.1 单例模式

spring配置文件,可以通过bean标签的scope属性设置bean的作用域范围

讯享网

在这里插入图片描述
测试方法:

 

在这里插入图片描述

5.2 多例模式

讯享网

测试方法:

 

在这里插入图片描述

6.1 具体的生命周期过程

  • bean对象创建(调用无参构造器)
  • 给bean对象设置属性
  • bean对象初始化之前操作 (由bean的后置处理器负责)
  • bean对象初始化(需在配置bean时指定初始化方法)
  • bean对象初始化之后操作(由bean的后置处理器负责)
  • bean对象就绪可以使用
  • bean对象销毁(需在配置bean时指定销毁方法)
  • lOC容器关闭

6.2 创建类对象

讯享网

6.3 配置bean

 

6.4 测试方法

讯享网

测试结果:
在这里插入图片描述

6.5 bean的后置处理器

bean的后置处理器会在生命周期的初始化前后添加额外的操作,需要实现BeanPostProcessor接口,且配置到I0C容器中,需要注意的是,

 

7.1 简介

FactoryBean是一个接口,需要创建一个类实现该接口其中有三个方法:

  • getObject():通过一个对象交给IOC容器管理
  • getObjectType(): 设置所提供对象的类型
  • isSingleton(): 所提供的对象是否单例

当把FactoryBean的实现类配置为bean时,会将当前类中getObject()所返回的对象交给IOC容器管理,就可以直接通过IOC容器getBena获取工厂getObject()所返回的对象

7.2 创建类UserFactoryBean

讯享网

FactoryBean接口

 

7.3 配置bean

讯享网

7.4 测试方法

 

测试结果:

在这里插入图片描述

8.1 概念

8.2 基于xml管理bean

场景模拟:三层架构:controller层-&gt;service层-&gt;dao层(mapper层)

讯享网
 

测试方法:

讯享网

结果:
在这里插入图片描述

7.3 基于xml的自动装配

自动装配的策略 autowire:

  • no,default:表示不装配,即bean中的属性不会自动匹配某个bean为属性赋值,此时属性使用默认值
  • byType:根据要赋值的属性的类型,在IOC容器中匹配某个bean,为属性赋值
    注意:
    a&gt; 若通过类型没有找到任何一个类型匹配的bean,此时不装配,属性使用默认值
    b&gt; 若通过类型找到了多个类型配的bean,此时会抛出异常:NoUniqueBeanDefinitionException
    总结:当使用byType实现自动装配时,IOC容器中有且只有一个类型匹配的bean能够为属性赋值
  • byName:将要赋值的属性的属性名作为bean的id在IOC容器中匹配某bean,为属性赋值
    总结:当类型匹配的bean有多个时,此时可以使用byName实现自动装配

在这里插入图片描述
spring配置文件:自动装配

 

8.4 基于注解管理bean(注解+扫描)

1. 注解

和 XML配置文件一样,注解本身并不能执行,注解本身仅仅只是做一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体操作。
本质上: 所有一切的操作都是java代码来完成的,XML和注解只是告诉框架中的java代码如何执行
举例:元旦联欢会要布置教室,蓝色的地方贴上元旦快乐四个字,红色的地方贴上拉花,黄色的地方贴上气球。

在这里插入图片描述
班长做了所有标记,同学们来完成具体工作。墙上的标记相当于我们在代码中便用的注解,后面同学们做的工作相当于框架的具体操作。

2. 扫描

spring配置文件开启组件扫描:

讯享网
3. 标识组件的常用注解

@Component: 将类标识为普通组件
@Controller: 将类标识为控制层组件
@Service: 将类标识为业务层组件
@Repository: 将类标识为持久层组件
通过注解+扫描所配置的bean的id,默认值为类的小驼峰,即类名的首字母为小写的结果,可以通过标识组件的注解的value属性值设置bean的自定义的id

在这里插入图片描述

以上四个注解的联系与区别?
通过查看源码我们得知,@Controller、@Service、@Repository这三个注解只是在@Component注解的基础上起了三个新的名字。
对于Spring使用IOC容器管理这些组件来说没有区别。所以@Controller、 @Service、@Repository这三个注解只是给开发人员看的,让我们能够便于分辨组件的作用。
注意:虽然它们本质上一样,但是为了代码的可读性,为了程序结构严谨我们肯定不能随便胡乱标记。

4. 创建类对象
 
5. 测试
讯享网

测试结果:
在这里插入图片描述

6. 扫描组件配置

context:exclude-filter:排除扫描

  • type:设置排除扫描的方式,type=“annotation | assignable”
  • annotation:根据注解的类型进行排除,expression需要设置排除的注解的全类名根据类的类型进行排除
  • assignable:根据类的类型进行排除,expression需要设置排除的类的全类名

context:include-filter:包含扫描

注意:需要在context:component-scan标签中设置use-default-filters=“false”

  • use-default-filters=“true”(默认),所设置的包下所有的类都需要扫描,此时可以使用排除扫描
  • use-default-filters=”false”,所设置的包下所有的类都不需要扫描,此时可以使用包含扫描

排除扫描:

 

包含扫描:

讯享网

8.5 基于注解的自动装配

1. 创建组件
 

测试方法:

讯享网

在这里插入图片描述

2. @Autowired:实现自动装配功能的注解
  1. @Autowired注解能够标识的位置

    a、标识在成员变量上,此时不需要设置成员变量的set方法

     

    b、标识在set方法上

    讯享网

    c、标识在为当前成员变量赋值的有参构造上

     
  2. @Autowired注解的原理

a&gt; 默认通过byType的方式,在IOC容器中通过类型匹配某个bean为属性赋值
b&gt; 若有多个类型匹配的bean,此时会自动转换为byName的方式实现自动装配的效果,即将要赋值的属性的属性名作为bean的id匹配某个bean为属性赋值
c&gt; byType和byName的方式都无法实现自动装配,即IOC容器中有多个类型匹配的bean且这些bean的id和要赋值的属性的属性名都不一致,此时抛异常:NOUniqueBeanDefinitionException
d&gt; 在c的基础上此时可以在要赋值的属性上,添加一个注解Qualifier通过该注解的value属性值,指定某个bean的id,将这个bean为属性赋值

讯享网

注意:
IOC容器中没有任何一个类型匹配的bean,此时抛出异常:NoSuchBeanDefinitionException。在@Autowired注解中有个属性required,默认值为true,要求必须完成自动装配可以将required设置为false,此时能装配则装配,无法装配则使用属性的默认值
在这里插入图片描述

二十三种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直接对目标方法进行调用,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来一解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护!

使用代理前:
在这里插入图片描述
使用代理后:

在这里插入图片描述

相关术语:

  • 代理:将非核心逻辑剥离出来以后,封装这些非核心逻辑的类、对象、方法
  • 目标:被代理“套用”了非核心逻辑代码的类、对象、方法。

2.1 创建接口对象

 

2.2 创建接口对象的实现类

讯享网

2.3 测试方法

 

2.4 总结

静态代理确实实现了解耦,但是由于代码都写死了,完全不具备任何的灵活性。就拿日志功能来说,将来其他地方也需要附加日志,那还得再声明更多个静态代理类,那就产生了大量重复的代码,日志功能还是分散的,没有统一管理。

提出进一步的需求:将日志功能集中到一个代理类中,将来有任何日志需求,都通过这一个代理类来实现这就需要使用动态代理技术了。

动态代理有两种:
1、jdk动态代理,要求必须有接口,最终生成的代理类和目标类实现相同的接口在com.sun.proxy包下,类名为$proxy+数字
2、cglib动态代理,最终生成的代理类会继承目标类,并且和目标类在相同的包下

3.1 创建代理对象工厂

讯享网

3.2 测试方法

 

4.1 概述

AOP (Aspect Oriented Programming) 是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程(OOP)的一种补充和完善,它以通过预编译方式和运行期动态代理方式实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。

4.2 相关术语

1. 横切关注点

在这里插入图片描述

2. 通知

每一个横切关注点上要做的事情都需要写一个方法来实现,这样的方法就叫通知方法。
前置通知: 在被代理的目标方法前执行
返回通知: 在被代理的目标方法成功结束后执行(寿终正寝)
异常通知: 在被代理的目标方法异常结束后执行(死于非命)
后置通知: 在被代理的目标方法最终结束后执行(盖棺定论)
环绕通知: 使用try…catch…finally结构围绕整个被代理的目标方法,包括上面四种通知对应的所有位置

各种通知的执行顺序:
Spring版本5.3.x以前:
前置通知
目标操作
后置通知
返回通知或异常通知。
Spring版本5.3.x以后:
前置通知
目标操作
返回通知或异常通知
后置通知

3. 切面

封装通知方法的类。

在这里插入图片描述

4. 目标

被代理的目标对象

5. 代理

为目标对象应用通知之后创建的代理对象

6.连接点

在这里插入图片描述

7. 切入点

定位连接点的方式
每个类的方法中都包含多个连接点,所以连接点是类中客观存在的事物 (从逻辑上来说)。
如果把连接点看作数据库中的记录,那么切入点就是查询记录的 SQL 语句。
Spring的AOP 技术可以通过切入点定位到特定的连接点。
切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件

4.3 作用

4.4 基于注解的AOP

在这里插入图片描述

  • 动态代理(lnvocationHandler) : JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口(兄弟两个拜把子模式)
  • cglib: 通过继承被代理的目标类(认干模式)实现代理,所以不需要目标类实现接口。
  • Aspect: 本质上是静态代理,将代理逻辑”织入”被代理的目标类编译得到的宁节码文件,所以最终效果是动态的。weaver就是织入器。Spring只是借用了Aspectj中的注解。
1. 添加依赖
讯享网
2. 配置spring文件
 
3. 创建目标对象
讯享网
4. 创建切面类

1.在切面中,需要通过指定的注解将方法标识为通知方法
@Before():前置通知,在目标对象方法执行之前执行
@After():后置通知,在目标对象方法的finally字句中执行
@AfterReturning():返回通知,在目标对象获取返回值之后执行
2.切入点表达式:设置在标识通知的注解的value属性中
execution(* com.fd.spring.annotation.CalculatorImpl.(…))
第一个
表示任意的访问修饰符和返回值类型
第二个表示类中任意的方法
…表示任意的参数列表
类的地方也可以使用
,表示包下所有的类
3.重用切入点表达式
@Pointcut声明一个公共的切入点表达式
@Pointcut(“execution(* com.fd.spring.annotation.CalculatorImpl.*(…))”)
public void pointCut() {}
使用方法:@After(“pointCut()”) //使用的是重用切入点表达式方法名
4.获取连接点信息
在通知方法的参数位置,设置JoinPoint类型的参数,就可以获取连接点所对应方法的信息
// 获取连接点所对应的方法名
Signature signature = joinPoint.getSignature();
// 获取连接点所对应方法的参数
Object[] args = joinPoint.getArgs();

 
5. 测试类

在spring中通过AOP代理后原目标对象就被隐藏了就不能再通过IOC获取原目标对象,只能通过接口去获取目标的代理对象

讯享网

测试结果:
在这里插入图片描述

6. 切面的优先级
 
讯享网

测试结果:

在这里插入图片描述

4.5 基于xml的AOP

1. 创建切面
 
2. 配置spring配置文件
讯享网
3. 测试方法:
 

测试结果:

在这里插入图片描述

Spring 框架对JDBC进行封装,使用JdbcTemplate 方便实现对数据库操作

1.1 引入依赖

讯享网

1.2 创建jdbc.properties

 

1.3 spring配置文件

讯享网

1.4 创建测试类

//指定当前测试类在Spring的测试环境中执行,此时就可以通过注入的方式直接获取IOC容器中bean
@RunWith(SpringJUnit4ClassRunner.class)
// 设置Spring测试环境的配置文件
@ContextConfiguration(“classpath:spring-jdbc.xml”)

 

(1) 事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
(2) 典型场景: 银行转账
luy 转账 100元给 mary
lucy少 100,mary多100

事务四个特性(ACID)

  • 原子性
  • 一致性
  • 隔离性
  • 持久性

2.1 编程式事务

事务功能的相关操作全部通过自己编写代码来实现

在这里插入图片描述

2.2 声明式事务

既然事务控制的代码有规律可循,代码的结构基本是确定的,所以框架就可以将固定模式的代码抽取出来,进行相关的封装。封装起来后,我们只需要在配置文件中进行简单的配置即可完成操作。

  • 好处1:提高开发效率
  • 好处2: 消除了几余的代码.
  • 好处3:框架会综合考虑相关领域中在实际开发环境下有可能遇到的各种问题,进行了健壮性、性能等各个方面的优化

所以,我们可以总结下面两个概念:

  • 编程式:自己写代码实现功能
  • 声明式:通过配置让框架实现功能

3.1 准备工作

1. 配置spring配置文件
讯享网

3.2 具体实现

1. 创建相关业务类

POJO层:

 

Controller层

讯享网

Service层

 

Dao层

讯享网
2. 测试事务
 

如果用户的余额不足报错,则图书的sql执行也会进行回滚。
在这里插入图片描述
SQL [update t_user set balance = balance - ? where id = ?]; Data truncation: Out of range value for column ‘balance’ at row 1; nested exception is com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Out of range value for column ‘balance’ at row 1

3.3 事务属性

1. readonly 只读

对一个查询操作来说,如果我们把它设置成只读,就能够明确告诉数据库,这个操作不涉及写操作。这样数据库就能够针对查询操作来进行优化。

注意:如果对增删改设置只读会抛出以下异常:
在这里插入图片描述

2. timeout 超时

事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源。而长时间占用资源大概率是因为程序运行出现了问题(可能是]ava程序或MySQL数据库或网络连接等等)。此时这个很可能出问题的程序应该被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执,概括来说就是一句话:超时回滚,释放资源。

讯享网

执行过程抛出异常:

在这里插入图片描述

3. rollbackFor 回滚策略
  • rollbackFor属性: 需要设置一个Class类型的对象。
  • rollbackForClassName属性: 需要设置一个字符串类型的全类名。
  • noRollbackFor属性: 需要设置一个Class类型的对象。
  • noRollbackForClassName属性: 需要设置一个字符串类型的全类名
 
4. isolation 事务隔离级别

数据库系统必须具有隔离并发运行各个事务的能力,使它们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别。SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱。

在这里插入图片描述
各个隔离级别解决并发问题的能力见下表:
在这里插入图片描述
各种数据库产品对事务隔离级别的支持程度:
在这里插入图片描述
事务隔离级别默认为:可重复读

讯享网
5. propagation 事务传播行为

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。

可以通过@Transactional中的propagation属性设置事务传播行为。

修改BookServicelmpl中buyBook()上,注解@Transactional的propagation属性

@Transactional(propagation = Propagation.REQUIRED),默认情况,表示如果当前线程上有已经开启的事务可用,那么就在这个事务中运行。经过观察,购买图书的方法buyBook()在checkout()中被调用,checkout()上有事务注解,因此在此事务中执行。所购买的两本图书的价格为80和50,而用户的余额为100,因此在购买第二本图书时余额不足失败,导致整个checkout()回滚,即只要有一本书买不了,就都买不了

@Transactional(propagation = Propagation.REQUIRES_NEN),表示不管当前线程上是否有已经开启的事务,都要开启新事务。同样的场暴,每次购买图书都是在buyBook()的事务中执行,因此第一本图书购买成功,事务结束,第二本图书购买失败,只在第二次的buyBook0中回滚,购买第一本图书不受影响,即能买几本就买几本

在这里插入图片描述

4.1 引入依赖

 

注意:基于xml的声明式事务必须引入Aspects的依赖

4.2 spring配置文件

讯享网

4.3 测试方法

 

小讯
上一篇 2025-04-15 08:38
下一篇 2025-05-22 15:10

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/159510.html