欢迎光临散文网 会员登陆 & 注册

教程揭秘 | 动力节点内部Java零基础教学文档第十篇:Spring

2023-11-14 09:30 作者:动力节点  | 我要投稿

接上期后续

本期分享第十章节

Spring

已经分享过半了,你们都跟上了吗?

每天都在学习嘛?

有什么不会的嘛?

今日教学文档分享来了 

今日新篇章

Spring

主要内容

1. 传统项目结构及问题

2. Spring框架的介绍

3. Spring的IOC介绍和原理

4. Spring的IOC的使用

5. Spring的AOP

6. Spring整合Mybatis

7. 声明式事务

8. 事务的传播性

学习目标


 

1. Spring框架的介绍

1.1 传统的项目的架构

 


在传统的项目中,一般遵循MVC开发模型。

(1) view层与用户进行交互,显示数据或者将数据传输给view层。

(2) 在controller层创建service层对象,调用service层中业务方法。

(3) 在service层创建dao层对象,调用dao层中操作数据的方法。

(4) dao层进行具体的数据库操作

1.2 传统的项目架构缺陷

程序在一定程度上存在耦合性,不利于程序的扩展。在controller中直接创建了service层类的对象。如果service的业务发生了变更,那么就需要修改controller层的代码。

 


在进行程序的扩展时,不建议在当前程序的基础上直接修改程序,为了保证之前程序的正常,一般遵循开闭原则进行维护性的修改,对扩展开放,对修改关闭。

例如:用户注册功能。用户注册,从账号、密码、手机号等信息即可。随着行业发展,目前要求进行实名认证。

1.已注册未认证用户登录时进行认证。

2.新用户注册后要求进行认证。

为避免对已有业务的改动,可以新建一个service类,重写注册方法。则在controller层需要创建新的service对象。每个相关的controller层的代码都需要改动,并且每个controller都需要创建对象,存在对象的浪费。

面向过程--->面向对象---->面向接口---->面向切面(组件)

ArrayList<String> aList = new ArrayList<String>();

List<String> aList = new LinkedList<String>()

1.3 解决方案

基于每个controller都要修改service的创建问题,可以为service定义一个统一的创建方式,例如对象工厂模式,使用工厂创建对象,这样以后使用工厂创建对象的对象需要维护时,只需要修改对象工厂即可,且可以结合单例模式,对象工厂返回单例,这样优化了对象重复的浪费问题。

 


虽然单例工厂能够解决对象的维护和重复问题。但是,随着service层的扩大,工厂也逐渐臃肿,基本每个service会对应一个factory。基于这种情况,则又需要解决工厂臃肿的问题,为此可以利用反射技术,反射可以创建任意类的对象。但是,工厂为保证单例,只能存储的对象只有一个,而controller层需要使用不同的service层对象,为保证对象的有效,且反射性能相对较低,基于这样的情况,则可以定义一个需要创建的对象的清单和一个存储对象的容器,根据清单创建对象,然后将所有创建service对象进行存储,每个controller只需要去容器中获取对象即可,这样既解决了单例问题,也提高了性能。

 


1.3.1 代码示例

 


1.3.2 对象清单

 

 


1.3.3 对象容器工厂

 

 

1.3.4 程序相关类

1.3.4.1 test

 

2. Spring的介绍

2.1 简介

Spring框架是由于软件开发的复杂性而创建的,初衷是为了让软件开发更加简单。Spring使用的是简单的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

Web Service,有2个显著特点:

1.数据格式是xml格式。

2.配置繁琐,“笨重”,对象关联性大,需在配置文件中各种配置。

基于这些原因,Spring框架提出了:IOC/DI(控制反转/依赖注入),AOP(面向切面编程)。

Spring框架可在任何类型的部署平台上为基于Java的现代企业应用程序提供全面的编程和配置模型。Spring的关键元素是在应用程序级别的基础架构支持:Spring专注于企业应用程序的“管道”,以便团队可以专注于应用程序级别的业务逻辑,而不必与特定的部署环境建立不必要的联系。

2.2 Spring的核心组件  

 


2.2.1 核心容器

核心容器由 spring-core,spring-beans,spring-context,spring-context-support和spring-expression(SpEL,Spring 表达式语言,Spring Expression Language)等模块组成,它们的细节如下:

l spring-core 模块提供了框架的基本组成部分,包括 IoC 和依赖注入功能。

l spring-beans 模块提供 BeanFactory,工厂模式的微妙实现,它移除了编码式单例的需要,并且可以把配置和依赖从实际编码逻辑中解耦。

l context 模块建立在由 core和 beans 模块的基础上建立起来的,它以一种类似于 JNDI 注册的方式访问对象。Context 模块继承自 Bean 模块,并且添加了国际化(比如,使用资源束)、事件传播、资源加载和透明地创建上下文(比如,通过 Servelet 容器)等功能。Context 模块也支持 Java EE 的功能,比如 EJB、JMX 和远程调用等。ApplicationContext 接口是 Context 模块的焦点。spring-context-support 提供了对第三方库集成到 Spring 上下文的支持,比如缓存(EhCache, Guava, JCache)、邮件(JavaMail)、调度(CommonJ, Quartz)、模板引擎(FreeMarker, JasperReports, Velocity)等。

l spring-expression 模块提供了强大的表达式语言,用于在运行时查询和操作对象图。它是 JSP2.1 规范中定义的统一表达式语言的扩展,支持 set 和 get 属性值、属性赋值、方法调用、访问数组集合及索引的内容、逻辑算术运算、命名变量、通过名字从 Spring IoC 容器检索对象,还支持列表的投影、选择以及聚合等。

依赖关系图如下:

 


2.2.2 数据访问/集成

数据访问/集成层包括 JDBC,ORM,OXM,JMS 和事务处理模块,它们的细节如下:

(注:JDBC=Java Data Base Connectivity,ORM=Object Relational Mapping,OXM=Object XML Mapping,JMS=Java Message Service)

l JDBC 模块提供了 JDBC 抽象层,它消除了冗长的 JDBC 编码和对数据库供应商特定错误代码的解析。

l ORM 模块提供了对流行的对象关系映射 API 的集成,包括 JPA、JDO 和 Hibernate 等。通过此模块可以让这些 ORM 框架和 spring的其它功能整合,比如前面提及的事务管理。

l OXM 模块提供了对 OXM 实现的支持,比如 JAXB、Castor、XML Beans、JiBX、XStream 等。

l JMS 模块包含生产(produce)和消费(consume)消息的功能。从 Spring 4.1 开始,集成了 spring-messaging 模块。

l 事务模块为实现特殊接口类及所有的 POJO 支持编程式和声明式事务管理。(注:编程式事务需要自己写 beginTransaction()、commit()、rollback() 等事务管理方法,声明式事务是通过注解或配置由 spring 自动处理,编程式事务粒度更细)

2.2.3 Web

Web 层由 Web,Web-MVC,Web-Socket 和 Web-Portlet 组成,它们的细节如下:

l Web 模块提供面向 web 的基本功能和面向 web 的应用上下文,比如多部分(multipart)文件上传功能、使用 Servlet 监听器初始化 IoC 容器等。它还包括 HTTP 客户端以及 Spring 远程调用中与 web 相关的部分。

l Web-MVC 模块为 web 应用提供了模型视图控制(MVC)和 REST Web服务的实现。Spring 的 MVC 框架可以使领域模型代码和 web 表单完全地分离,且可以与 Spring 框架的其它所有功能进行集成。

l Web-Socket 模块为 WebSocket-based 提供了支持,而且在 web 应用程序中提供了客户端和服务器端之间通信的两种方式。

l Web-Portlet 模块提供了用于 Portlet 环境的 MVC 实现,并反映了 spring-webmvc 模块的功能。

2.2.4 其他

还有其他一些重要的模块,像 AOP,Aspects,Instrumentation,Web 和测试模块,它们的细节如下:

l AOP 模块提供了面向方面(切面)的编程实现,允许你定义方法拦截器和切入点对代码进行干净地解耦,从而使实现功能的代码彻底的解耦出来。使用源码级的元数据,可以用类似于.Net属性的方式合并行为信息到代码中。

l Aspects 模块提供了与 AspectJ 的集成,这是一个功能强大且成熟的面向切面编程(AOP)框架。

l Instrumentation 模块在一定的应用服务器中提供了类 instrumentation 的支持和类加载器的实现。

l Messaging 模块为 STOMP 提供了支持作为在应用程序中 WebSocket 子协议的使用。它也支持一个注解编程模型,它是为了选路和处理来自 WebSocket 客户端的 STOMP 信息。

l 测试模块支持对具有 JUnit 或 TestNG 框架的 Spring 组件的测试。

3. Spring的IOC的使用  IOC、DI

IOC:控制反转。将对象的创建、初始化、销毁等一系列的生命周期过程交给spring管理。

结婚:

方式1: 自己找女生--------------->吃饭、逛街、看电影、送回家等--------->结婚

(同学、同事、公交地铁1个月-3个月)            半年-1年半                  1天

方式2: 媒婆(1个月)------------------------>结婚(1天)

 

吃饭:

方式1:  买菜、买米(30min-1h)---->蒸饭、洗菜、切菜、炒菜(1个小时)--->吃(15-30min)

方式2:  定外卖----------------->吃(15-30min)

 

面向过程----->面向对象----->面向接口----->面向组件(面向切面)-->面向服务--->面向百度

3.1 基本使用

3.1.1 创建项目并导入spring IoC相关jar包



3.1.2 创建User类

 

 

3.1.3 创建Spring的核心配置文件spring-context.xml/applicationContext.xml

3.1.4 编写测试程序

3.2 Bean标签属性介绍

3.2.1 id

是 bean的唯一标识 一个bean,其id 值只能有一个 。整个IOC 容器id 值不允许重复,使用名称作为key。

3.2.2 name

一个bean的名称,可以存在多个,多个之间使用逗号分隔。不论bean有没有定义name属性,默认id都会当做name。

3.2.3 class

bean的具体的类型,包名和类名组成。

3.2.4 scope

bean的作用域:如果不写scope,则默认为单例

prototype :非单例,每次获取都会创建一个新的bean对象。

singleton : 单例,多次获取永远同一个bean, 默认值。

request : 一次请求,基于web项目的bean的作用域。

session : 一次会话,基于web项目的bean的作用域。

3.2.5 lazy-init

延迟初始化(懒加载),默认只要加载了配置文件。bean对象就会被初始化,lazy-init则是获取时才会初始化。只针对单例模式有效,非单例每次获取都会创建,没有延迟初始化的意义

3.2.6 depends-on

初始化时依赖的对象,当前对象初始化前需先初始化depends-on指定的对象

3.2.7 init-method

对象初始化后,调用的方法

3.2.8 destroy-method

对象销毁时,调用的方法

3.2.9 autowire

属性自动装配

byName 根据属性名称装配

byType 根据类型装配

3.2.10 autowire-candidate

是否允许作为自动装配的候选项

true 作为自动装配的候选项

false 不作为自动装配的候选项

3.2.11 primary

优先使用该bean,因为Spring需要支持使用类型查找对象,在一个大类型下,可能存在多个小类型。如果根据大类型装配属性时,不知道使用哪个具体的对象,则可以根据primary设置优先级。

3.2.12 代码示例

 

3.3 Bean对象创建的4种方式

3.3.1 构造方法创建

使用构造方法创建bean对象,是spring默认的创建方式。

<!-- 使用构造方法创建对象 -->
<bean id="user" class="com.bjpowernode.domian.User" />

 

3.3.2 静态工厂创建

 

3.3.3 非静态工厂创建

 

3.3.4 注解创建

Spring为简化对象的创建方式,提供了注解。

3.3.4.1 组件注解:

3.3.4.1.1 @Component(bs)   <bean id=bs class=xxxx>

表示该类为一个被Spring管理的组件。但是,由于在开发中为了让代码的可读性更高。

Spring基于分层思想,将需要创建的组件分为以下几类:

3.3.4.1.2 @Controller

@Controller注解,标识该类是controller层的类。并且,注意在使用SpringMVC时,所有的Constroller,必须使用@Controller注解。

3.3.4.1.3 @Service

@Service注解,标识该类是业务层的类。

3.3.4.1.4 @Respository

@Respository注解,标识该类是操作数据层的类。

注意:

以上注解是Spring中定义的创建对象的注解,都可以创建对象,如果该类有明确的作用,有自己所属的层,则建议使用相应的注解,如果实在无法区分该类所属层,可以使用@Component注解。

3.3.4.2 注解使用步骤

3.3.4.2.1 开启组件扫描

在spring的核心配置文件中,开启注解扫描,让Spring将被注解修饰的类,创建对相关。

xml头部

 

3.3.4.2.2 添加注解

 

3.3.5 什么时候使用XML配置和注解  

能使用注解时,就使用了注解,注解非常方便。但是,在第三方的类中,是无法使用注解的。因为无法在别人提供的源码上加上Spring注解,此时只能使用XML配置的形式,配置第三方类的Bean信息。

3.4 IOC属性注入的3种方式

为对象属性设置值,就是属性注入。

3.4.1 构造方法属性注入:DI(依赖注入,给对象的属性赋值)  

 

 

3.4.2 set方法属性注入

 

3.4.3 注解属性注入

在spring中,为了简化属性的注入,Spring提供注解:@Autowired,Spring会自动从IOC容器中,为这个属性查找相应类型的值,进行注入。

1. 开启包的注解扫描

<context:component-scan base-package="com.*" />

2. 使用注解

 

注意:

在使用自动注入时,可以在bean标签上,配置autowire,但是此时必须有该属性的set方法,@Autowired注解,是不需要set方法的。

如果是在xml中注入对象,值使用ref属性。value属性,只支持boolean,数字,字符串等。

3.5 常见类型的属性注入

在Spring中,提供了丰富的标签,进行各种属性的注入。常见的类型:

数字、字符串、boolean、数组、set、list、map、properties。

3.6 使用IOC容器,改造传统项目

3.6.1 xml配置版

3.6.1.1 创建项目并加入依赖

 


3.6.1.2 项目结构

 


3.6.1.3 配置文件

 

3.6.1.4 controller

 

3.6.1.5 dao

 

3.6.1.6 service

 

 

3.6.1.7 test

 

3.6.2 注解版

3.6.2.1 配置文件

 

3.6.2.2 controller

 

3.6.2.3 dao

 

 

3.6.2.4 service

 

3.6.2.5 test

4. AOP

com.powernode.aadenglu

Login: login():登录方法

 

com.powernode.anquan

Security: isSecurity():检测操作环境是否安全

 

com.powernode.bmapper  

CBCBankMapper(核心类): selectMoney() updateMoney() updateInvest() update2Tel()

 

com.powernode.crizhi

Logger: log():记录用户操作细节

 

com.powernode.dqinli

Clean :cleanResource():清理缓存

 

Expt:  handExpt()

 

4.1 AOP简介:面向切面(面向组件)

DefaultAopProxyFactory

代理

静态代理

静态代理,每个被代理类都需要创建对应的代理类。随着程序的扩展,代理类也会增多,臃肿,维护量变多,为了解决这个问题,Java中,提供了动态代理技术,开发者不需要自己定义代理类,代理类由JDK动态的创建,开发只需要指定被代理的类即可。

切面(aspect):除了核心类以外的其他类称之为切面

通知(advisor):切面中的方法称之为通知

核心类:一个项目中不能省略的模块类

核心方法:核心类中的方法称之为核心方法

连接点:核心类中的某一个方法

切入点(pointcut):某个包下的某个类下的某一批方法

代理(proxy):将多个切面与核心类组合在一起,形成一个新的类,这个类称之为代理类

织入(weaver):书写代理类的过程称之为织入

4.2 动态代理

4.2.1 JDK动态代理

4.2.1.1 Proxy

该类提供了方法创建代理类和代理类的对象的方法

创建一个代理类并返回代理类对象

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  

loader : 类加载器,指定类加载器,是为了精确的定位类

interfaces : 接口Class类,使用JDK的反射,必须要有接口

h :InvocationHandler ,代理的处理器,每个代理类都有一个关联的处理器

4.2.1.2 InvocationHandler

是每个代理类对应的处理器

Object  方法调用的返回值,可以作为被代理的方法调用的返回值

proxy : 代理类对象

method : 目标类中被代理的方法

args : 目标类中被代理的方法的运行参数

Object invoke(Object proxy,Method method,Object[] args)

4.2.1.3 代码示例

4.2.1.3.1 目标类接口

 

 

4.2.1.3.2 目标类

 

 

4.2.1.3.3 代理类处理器

 

 

4.2.1.3.4 测试类

 

4.2.1.3.5 生成代理类源码

 

4.2.1.3.6 JDK动态代理的不足

在JDK中使用动态代理,必须有类的接口。因为生成的代理需要实现这个接口,这样我们生成的代理类对象,才能转化为代理目标的接口对象,然后根据接口中的方法,调用处理器中invoke方法。

 


4.2.2 Cglib动态代理

为了弥补JDK动态代理的不足,第三方组织封装一套工具包,cglib的工具包,这套包不基于接口,基于父子继承,通过重写的形式扩展方法,但是这个子类工具自动生成的。

早期,Cglib动态代理,性能相于JDK的动态代理高一些。JDK进行一些列优化,目前Spring默认使用的动态代理JDK,也支持Cglib。

4.2.2.1 Cglib动态代理的使用

4.2.2.1.1 MethodInterceptor  

cglib中,提供的对方法执行拦截的接口。其中intercept是对具体方法进行拦截处理的方法。

 public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,

                               MethodProxy proxy)

Object  : 方法执行返回的结果

obj :增强类的对象

method :目标方法

proxy :用于回调的方法的对象

4.2.2.1.2 代码示例

4.2.2.1.2.1 导入jar包

 

4.2.2.1.2.2 创建被代理目标类

 

4.2.2.1.2.3 方法拦截器

 

4.2.2.1.2.4 测试类

 

4.2.2.2 动态代理的不足

不论是JDK的动态代理,还是第三方cglib动态代理,都需要开发者编写代码处理程序。程序结构基本上大同小异,重复造轮子。基于这样的情况,在Spring中,提供了2种方式:xml配置形式和注解形式,使用动态代理。这种模式就是Spring Aop技术。其底层依然是动态代理。

4.3 Spring的AOP配置

在Spring中,AOP的配置主要分为2类:xml配置和注解配置

XML配置也分为两种,一种Spring的原生支持,一种是Spring的aspects这个相关的框架。

4.3.1 AOP的相关概念

连接点(JoinPoint):所谓连接点是指那些被拦截的点,而spring中这些点就是指方法,因为spring只支持方法类型的连接点。

切入点(PointCut):所谓切入点就是指我们要对那些JoinPoint进行拦截的定义,指的是具体的拦截的位置

增强/通知(Advice) : 增强就是对具体的连接点进行扩展的功能。由于一般对方法进行增强,分为在方法前执行或者方法后,或者发生异常执行等等,所以增强被分为:前置增强(前置通知)、后置增强(后置通知)、环绕通知(环绕增强)、异常增强(异常通知)

引介(Introduction):引介是一种特殊的Advice,在不修改代码的前提下,引介可以在运行期为类动态的添加一些方法或Field.

目标(Target) :被代理的类(需要增强类)

织入(Weaving) :把Advice应用到Target的过程

代理(Proxy):使用AOP配置后产生的代理类

切面(Aspect):切点和增强整合形成了切面

 


4.3.2 Spring自身AOP具体配置

4.3.2.1 引入aop相关jar包

 

4.3.2.2 定义增强类

4.3.2.2.1 前置增强-MethodBeforeAdvice

4.3.2.2.2 后置增强-AfterReturningAdvice

 

4.3.2.2.3 环绕增强-MethodInterceptor

 

4.3.2.2.4 异常增强-ThrowsAdvice

 

4.3.2.3 目标类

 

4.3.2.4 aop配置

 

4.3.2.5 测试类

 

4.3.3 AspectJ框架AOP配置

在原生的spring中,每种增强都需要单独定义一个类实现相应的接口。增强类本身就更庞大,而且方法的名称是固定的。基于这种情况,AspectJ提供了相对更加灵活的方式。

在AspectJ中,只需要定义一个增强类即可,并且方法的名称可以任意定义。

4.3.3.1 引入相关jar

 

 

4.3.3.2 编写增强类

 

 

4.3.3.3 编写目标类

 

4.3.3.4 配置AspectJ的增强配置

 

4.3.3.5 进行测试

 

 

4.3.4 AspectJ的AOP注解方式

4.3.4.1 引入相关jar包

 

4.3.4.2 定义增强类

 

4.3.4.3 目标类

 

 

4.3.4.4 开启相关注解

 

 

4.3.4.5 测试类

5. Spring整合Mybatis

Spring整合Mybatis就是将Mybatis交给Spring进行管理,将Mybatis的SqlSession对象,放入IOC容器中,并且可以利用自动装配功能,为每个数据库操作层,注入SqlSession。并且Spring内置可以有代理的,可以根据SqlSession对象及数据操作接口,创建Mapper接口的代理对象,此时Mapper的代理在IOC容器中,那么可以将Mapper接口的对象注入到Service中。

5.1 多XML版

使用配置文件版本,Mybatis配置文件和Spring配置文件是单独的。

5.1.1 引入相关jar包

5.1.1.1 spring相关jar包

5.1.1.2 mybatis相关jar包

 

5.1.1.3 数据库相关jar包

 

5.1.1.4 日志相关jar包

5.1.1.5 spring和mybatis整合包

5.1.1.6 mybatis分页插件包

5.1.2 相关类

5.1.2.1 domain

 

5.1.2.2 mapper

 

5.1.2.3 service

 

5.1.2.4 测试类

 

5.1.3 相关配置文件

5.1.3.1 jdbc配置文件

5.1.3.2 日志配置文件

5.1.3.3 mybatis核心配置文件

5.1.3.5 spring核心配置文件

5.2 Spring配置文件版

使用Spring的配置文件,取代mybatis的核心配置文件。

导入的jar包和相关类完全一致,jdbc配置文件和日志配置文件也相同。只是将mybatis的核心配置文件中的配置,移入到spring的核心配置文件中。

5.2.1 Spring核心配置文件

 

5.2.2 配置日志

 

6. 声明式事务

在spring中,spring可以管理数据源,管理连接,spring也可以管理事务,并且spring单独对事务分了一个模块进行管理。并且,Spring简化了事务开发,只需要通过配置的方式,Spring即可对事务进行统一完善的管理,Spring的事务管理基于Spring的AOP技术。

Spring的声明式事务,有两种方式:xml配置、注解

6.1 XML配置方式

6.2 注解版声明式事务

在Spring中,为简化事务开发,提供了注解:@Transactional,该注解可以指定在类上,在类上,该类中的所有方法都会使用事务,该注解也可以指定方法上,该方法会使用事务。使用非常简单,只需:

1. 配置事务管理器

2. 开启注解事务

3. 在需要使用事务的地方使用@Transactional

6.2.1 配置类

 

6.2.2 service代码

7. 2


注意:

事务的传播行为,是指事务会发生传递。例如:A方法存在事务,A调用B方法,那么B方法也会在事务中执行,这种就是事务的传播行为。


更多干货我们下期再说!

下期会分享

第十一章节

SpringMVC

相关知识~

下期见!


教程揭秘 | 动力节点内部Java零基础教学文档第十篇:Spring的评论 (共 条)

分享到微博请遵守国家法律