写点什么

阿里专家带你用 Spring 快速搭建项目,剖析万能框架的“五脏六腑”

发布于: 2 小时前
阿里专家带你用Spring快速搭建项目,剖析万能框架的“五脏六腑”

今日分享开始啦,请大家多多指教~

了解一下“代理模式”

为什么要学习代理模式,因为 Spring AOP 的底层机制就是动态代理!

代理模式的分类

代理模式就是创建一个代理对象,由代理对象来接管原对象的引用。

  • 静态代理

  • 动态代理

上图通过“租房”的例子讲了一下代理模式的核心!

静态代理

静态代理角色分析

  • 抽象角色 : 一般使用接口或者抽象类来实现。

  • 真实角色 : 被代理的角色。

  • 代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作。

  • 客户 : 使用代理角色来进行一些操作。

以租房为例,我们体验一下代码实现:

定义一个抽象接口:

房东类:

中介类:


房客类:

运行结果:

案例二:加深理解静态代理!!!

同学们练习完毕后,我们再来举一个例子,巩固大家的学习!

练习步骤:

1、创建一个抽象角色,比如咱们平时做的用户业务,抽象起来就是增删改查!

2、我们需要一个真实对象来完成这些增删改查操作

3、需求来了,现在我们需要增加一个日志功能,怎么实现!

  • 思路 1 :在实现类上增加代码 【麻烦!】

  • 思路 2:使用代理来做,能够不改变原来的业务情况下,实现此功能就是最好的了!

4、设置一个代理类来处理日志!(代理角色)


5、测试访问类:

运行结果:

OK,到了现在代理模式大家应该都没有什么问题了,重点大家需要理解其中的思想;

我们在不改变原来的代码的情况下,实现了对原有功能的增强,这是 AOP 中最核心的思想!!!

静态代理的好处:

可以使得我们的真实角色更加纯粹,不再去关注一些公共的事情。

公共的业务由代理来完成,实现了业务的分工 。

公共业务发生扩展时变得更加集中和方便。

缺点 :

类多了 ,多了代理类,工作量变大了 ,开发效率降低 。

我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !

动态代理

动态代理的角色和静态代理的一样。

动态代理的代理类是动态生成的 . 静态代理的代理类是我们提前写好的。

动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理。

  • 基于接口的动态代理----JDK 动态代理

  • 基于类的动态代理–cglib

  • 基于 java 字节码实现,现在用得比较多的是 javasist 来生成动态代理

我们这里使用 JDK 的原生代码来实现,其余的道理都是一样的!

JDK 的动态代理需要了解两个类核心 : InvocationHandler 和 Proxy。

InvocationHandler:调用处理程序

InvocationHandler 是由代理实例的调用处理程序实现的接口。每个代理实例都有一个关联的调用处理程序。 现在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的 invoke 方法。

处理代理实例上的方法调用并返回结果。当在与之关联的代理实例上调用方法时,将在调用处理程序中调用此方法。

参数解析:

  • proxy -调用该方法的代理实例。

  • method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。

  • args -包含的方法调用传递代理实例的参数值的对象的阵列,或 null 如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如 java. lang. Integer 或 java.lang . Boolean。

Proxy:代理类

  • public class Proxy

  • extends Object

  • implements Serializable

Proxy 提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。

为某个接口创建代理 Foo:

或更简单的:

该类中所有的方法:

通过代码来实际体验:

先创建一个抽象角色:rent

再创建一个真实角色:host

创建代理角色:ProxyInvocationHandler


测试代码:

运行结果:

我们来使用动态代理实现代理我们前面写的 UserService!

我们也可以编写一个通用的动态代理实现的类!所有的代理对象设置为 Object 即可!把它当做一个工具类使用即可~~


测试代码:

运行结果:

动态代理的好处:

静态代理有的它都有,静态代理没有的,它也有!

  • 可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情 .

  • 公共的业务由代理来完成 . 实现了业务的分工 ,

  • 公共业务发生扩展时变得更加集中和方便 .

一个动态代理类代理的是一个接口 , 一般就对应的某一类业务

一个动态代理类可以代理多个类,只要是实现了同一个接口就行

Aspect Oriented Programming-AOP

什么是 AOP?

AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP 是 OOP 的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

Aop 在 Spring 中的作用

提供声明式事务;

允许用户自定义切面。

以下名词需要了解下:

  • 横切关注点 :跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志 , 安全 , 缓存 , 事务等等 …

  • 切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类。

  • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。

  • 目标(Target):被通知对象。

  • 代理(Proxy):向目标对象应用通知之后创建的对象。

  • 切入点(PointCut):切面通知 执行的 “地点”的定义。

  • 连接点(JointPoint):与切入点匹配的执行点。

SpringAOP 中,通过 Advice 定义横切逻辑,Spring 中支持 5 种类型的 Advice:

即 Aop 在 不改变原有代码的情况下 , 去增加新的功能 。

使用 Spring 实现 AOP

使用之前,需要在配置文件中导入一个依赖包!!!

方式一:使用 Spring API 实现

首先编写我们的业务接口和实现类:


然后去写我们的增强类 , 我们编写两个 , 一个前置增强 一个后置增强:


最后去 spring 的文件中注册 , 并实现 aop 切入实现 , 注意导入约束 :

测试代码:

运行结果:

方式二:自定义类来实现 AOP

目标业务类不变依旧是 userServiceImpl,首先, 写我们自己的一个切入类:

去 Spring 中配置 applicationContext.xml 文件:


测试代码:

运行结果:

方式三:使用注解实现 AOP

首先,编写一个注解实现的增强类:


在 Spring 配置文件中,注册 bean,并增加支持注解的配置:

测试代码:

运行结果:

整合 MyBatis

首先,导入 jar 包:



编写配置文件:

测试代码:

运行结果:

Mybatis-Spring 学习

什么是 MyBatis-Spring?

MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。

整合方式 1

主要步骤:

  • 引入 Spring 配置文件 applicationContext.xml

  • 编写数据源配置,替换 mybatis 的数据源

  • 配置 sqlSessionFactory,,关联 mybatis

  • 注册 sqlSessionTemplate,关联 sqlSessionFactory

  • 增加接口实现类,私有化 sqlSessionTemplate

  • 注册 bean 实现

  • 测试代码

配置文件:


接口实现类:

测试代码:

整合方式 2

声明式事务

事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。

事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。

事务四个属性 ACID:

  • 原子性(atomicity):事务是原子性操作,由-系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用。

  • 一致性 (consistency):一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中。

  • 隔离性(isolation):可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。

  • 持久性(durability):事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中。

案例 1:

创建一个 User 类:

创建 UserMapper 接口:

配置 Mapper 文件,故意把 delete 写错,进行测试:

编写接口的实现类,在实现类中去操作一波~:

运行结果:

我们发现,运行报错: sq|异常, 这很正常,因为 delete 写错了! 但是,数据库结果:插入成功!

这就是因为,没有进行事务的管理,我们想让他们都成功才成功,有一个失败, 就都失败,我们就应该需要进行事务管理!

Spring 中的事务管理

以前我们都需要自己手动管理事务,十分麻烦!但是 Spring 给我们提供了事务管理,我们只需要配置即可。

Spring 在不同的事务管理 API 之上定义了一个抽象层,使得开发人员不必了解底层的事务管理 API 就可以使用 Spring 的事务管理机制。Spring 支持编程 式事务管理和声明式的事务管理。

编程式事务管理

  • 将事务管理代码嵌到业务方法中来控制事务的提交和回滚

  • 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

声明式事务管理

  • 一般情况下比编程式事务好用。

  • 将事务管理代码从业务方法中分离出来,以以明的方式来实现事务管理。

  • 将事务管理作为横切关注点,通过 aop 方法模块化。Spring 中通过 Spring AOP 框架支持声明式事务管理。

步骤:

  • 使用 Spring 管理事务,注意头文件的约束导入:tx

  • 事务管理器,无论使用 Spring 的哪种事务管理策略,事务管理器都是必须的。(就是 Spring 的核心事务管理抽象,封装了一组独立于技术的方法)

  • 配置好事务管理器后,我们需要去配置事务的通知。Spring 的事务传播特性如下图所示:

  • 配置 AOP

测试结果:

为什么需要配置事务?

●如果不配置,就需要我们手动提交控制事务;

●事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!

今日份分享已结束,请大家多多包涵和指点!

用户头像

还未添加个人签名 2021.04.20 加入

Java工具与相关资料获取等WX: gsh950924(备注来源)

评论

发布
暂无评论
阿里专家带你用Spring快速搭建项目,剖析万能框架的“五脏六腑”