Spring 简介
1 Spring 介绍
Spring 是一个开源框架,最早由 Rod Johnson 发起。Spring 为简化企业级开发而生,使
用 Spring 开发可以将 Bean 对象交给 Spring 容器来管理,这样使得很多复杂的代码在 Spring
中开发会变得非常的优雅和简洁,有效的降低代码的耦合度,极大的方便项目的后期维护、
升级和扩展。
2 Spring 的四种关键策略
基于 POJO 的轻量级和最小侵入性编程;
通过依赖注入和面向接口实现松耦合;
基于切面和惯例进行声明式编程;
通过切面和模板减少样板式代码;
3 Spring 特点
非侵入式:基于 Spring 开发的应用中的对象可以不依赖于 Spring 的 API。
容器:Spring 是一个容器,因为它包含并且管理应用对象的生命周期。
控制反转:IOC (Inversion of Control),指的是将对象的创建权交给 Spring 去创建。
使用 Spring 之前,对象的创建都是由我们自己在代码中 new 创建。而使用 Spring
之后。对象的创建都是由给了 Spring 框架。
依赖注入:DI (Dependency Injection),是指依赖的对象不需要手动调用 setXX 方法去设置,而是通过配置赋值。
面向切面编程:Aspect Oriented Programming——AOP。
组件化:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用 XML 和 Java 注解组合这些对象。
一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库。
SpringIOC 容器
1.1IOC 思想
IOC (Inversion of Control) 是指在程序开发中,对象实例的创建不再由调用者管理,而是
由 Spring 容器创建。Spring 容器会负责控制程序之间的关系,而不是由程序代码直接控制,
因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转,这就是 Spring 的
1.2IOC 容器概念
IOC 容器就是具有依赖注入功能的容器,IOC 容器负责实例化、定位、配置应用程序中
的对象及建立这些对象间的依赖。应用程序无需直接在代码中 new 相关的对象,应用程序
由 IOC 容器进行组装。在 Spring 中 BeanFactory 是 IOC 容器的实际代表者。
1.3Bean 的概念
在 Spring 中,被 Spring 容器所管理的对象称之为”Bean”对象。一个 Spring 的 Bean 对象
可以是任何形式的 POJO。
2 Spring IOC 容器类型
Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext。
2.1BeanFactory
BeanFactory 是基础类型的 IoC 容器。
它由 org.springframework.beans.facytory.BeanFactory 接口定义,并提供了完整的 IoC
服务支持。简单来说,BeanFactory 就是一个管理 Bean 的工厂,它主要负责初始化各种
Bean,并调用它们的生命周期方法。
2.2ApplicationContext
ApplicationContext 是 BeanFactory 的子接口,也被称为应用上下文。该接口的全路径为org.springframework.context.ApplicationContext,它不仅提供了 BeanFactory 的所有功能,
还添加了对国际化、资源访问、事件传播等方面的良好支持。
ApplicationContext 接口有两个常用的实现类:
2.2.1 ClassPathXmlApplicationContext
该 类 从 类 路 径 ClassPath 中 寻 找 指 定 的 XML 配 置 文 件 , 找 到 并 装 载 完 成
ApplicationContext 的实例化工作。
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);
FileconfigLocation 参数用于指定 Spring 配置文件的名称和位置。
2.2.2 SystemXmlApplicationContext
该类从指定的文件系统路径中寻找指定的 XML 配置文件,找到并装载完成
ApplicationContext 的实例化工作。
ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation)
它与 ClassPathXmlApplicationContext 的区别是:在读取 Spring 的配置文件时,
FileSystemXmlApplicationContext 不再从类路径中读取配置文件,而是通过参数指定配置文
件的位置,它可以获取类路径之外的资源,如“F:/workspaces/applicationContext.xml”;
Spring IOC 容器创建 Bean 对象的三种方式
1、 通过构造方法创建 Bean 对象
2、创建静态工厂方法
3.通过动态工厂方法创建对象
在 Spring IOC 容器中获取 Bean 对象的方式
DI 依赖注入
对于 Spring IOC 容器而言我们更多的是使用它的依赖注入。 Spring 创建对象的过程叫做 IOC,创建对象时给对象属性赋值叫做 DI,所以我们可以认为 IOC 和 DI 是同一个事情。
1. 什么是依赖注入
DI (Dependency Injection):依赖注入是指在 Spring IOC 容器创建对象的过程中,将所
依赖的对象通过配置进行注入。我们可以通过依赖注入的方式来降低对象间的耦合度。
在软件工程中,对象之间的耦合度就是对象之间的依赖性。对象之间的耦合越高,维护
成本越高,因此对象的设计应使对象之间的耦合越小越好。
依赖注入的方式
在使用依赖注入时,如果注入的是 Bean 对象,那么要求注入的 Bean 对象与被注入的
Bean 对象都需要 Spring
通过 Set 方法注入
需要为注入的成员变量提供 Set 方法。
通过构造方法注入
Bean 对象中需要提供有参的构造方法
自动注入
自动注入的方式有两种,一种是全局配置自动注入,另一种是局部配置自动注入。
无论全局配置或局部单独配置,都有 5 个值可以选择:
no:当 autowire 设置为 no 的时候,Spring 就不会进行自动注入。
byName:在 Spring 容器中查找 id 与属性名相同的 bean,并进行注入。需要提供 set 方法。
byType:在 Spring 容器中查找类型与属性名的类型相同的 bean,并进行注入。需要提供 set 方法。
constructor:仍旧是使用 byName 方式,只不过注入的时候,使用构造方式进行注入。
default:全局配置的 default 相当于 no,局部的 default 表示使用全局配置设置。
依赖注入的数据类型
代理模式
1 什么是代理模式
代理模式(Proxy Pattern):代理模式是 Java 常见的设计模式之一。所谓代理模式是指客
户端并不直接调用实际的对象,而是通过调用代理对象,来间接的调用实际的对象。通俗的
来讲代理模式就是我们生活中常见的中介。
2 为什么使用代理模式
隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类
对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
开闭原则:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额
外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合
代码设计的开闭原则。
代理模式的优点:
代理模式能将代理对象与真实对象被调用的目标对象分离。
一定程度上降低了系统的耦合度,扩展性好。
保护目标对象。
增强目标对象。
代理模式的缺点:
代理模式会造成系统设计中类的数目的增加。
在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢
增加了系统的复杂度。
3 代理模式的实现
代理模式可以分为两种:静态代理、动态代理。
3.1静态代理
静态代理模式由三个部分构成:
一个公共的接口
一个被代理角色
一个代理角色
动态代理的实现
在动态代理中分为两种实现方式:
使用 JDK 的 Proxy 类实现动态代理
使用 CGLIB 实现动态代理
AOP 编程
1.1什么是 AOP
AOP 的全称是 Aspect Oriented Programming,即面向切面编程,它将业务逻辑的各个部
分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。
AOP 采取横向抽取机制,取代了传统纵向继承体系的重复性代码,其应用主要体现在
事务处理、日志管理、权限控制、异常处理等方面。
目前最流行的 AOP 技术有两个,分别为 Spring 框架的 AOP 和 AspectJ 框架。
1.2什么是面向切面编程
把一个个的横切关注点放到某个模块中去,称之为切面。每个切面影响业务的一种功能,
切面的目的就是为了功能增强,将需要增强的方法做成切面,实现对业务的增强,就是面向
切面编程。
面向切面编程的目的:将与业务本身无关,却被业务模块所共同调用的功能代码封装成
切面,以减少系统的重复代码,降低耦合,提高可扩展性。
面向切面编程的优势:把多个方法前/后的共同代码抽离出来,使用动态代理机制来控
制,先执行抽离出来的代码,再执行每一个真实方法。
AspectJ 框架
示例一:
execution(public * com.bjsxt.service.impl.Student.test())
切点是 com.bjsxt.service.impl 包中 Student 类中所有 public 修饰的无参数的 test方法。
示例 2:
execution(* com.bjsxt.service.impl.Student.test(String,int))
切点是 com.bjsxt.service.impl 包中 Student 类中参数类型是 String,int 类型的 test方法。
示例 3:
execution(* com.bjsxt.service.impl.Student.test(…))
切点是 com.bjsxt.service.impl 包中 Student 类中任意参数的 test 方法。
示例 4
execution(* com.bjsxt.service..(…))
切点是 com.bjsxt.service 包中所有接口中任意参数的所有方法。
注解配置切面方式:
Spring 事务管理
解决办法(四种隔离级别)
1、Read Uncommited(读取未提交内容)
读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。但是,读未提
交产生了脏读,采用 Read Commited 可以解决脏读问题
2、Read Commited(读取提交内容)
读提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。读提交,若有
事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能
读取数据,可以解决脏读问题。但是,读提交两次查询会产生不同的查询结果,就会造成不
可重复读问题,采用 Repeatable Read 可以解决此问题。
3、Repeatable Read(重复读)
重复读,就是在开始读取数据(事务开启)时,不再允许修改操作。重复读可以解决不
可重复读问题。应该明白的一点就是,不可重复读对应的是修改,即 UPDATE 操作。但是可
能还会有幻读问题。因为幻读问题对应的是插入 INSERT 操作,而不是 UPDATE 操作。采用
Serializable 可以解决幻读问题
4、Serializable(可串行化)
Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。
Yes:可能出现。No:不会出现
注意:
大多数数据库默认的事务隔离级别是 Read committed,比如 Sql Server , Oracle。
Mysql 的默认隔离级别是 Repeatable read。
隔离级别的设置只对当前链接有效。对于使用 MySQL 命令窗口而言,一个窗口就
相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效;对于 JDBC
操作数据库来说,一个 Connection 对象相当于一个链接,而对于 Connection 对象
设置的隔离级别只对该 Connection 对象有效,与其他链接 Connection 对象无关。
基于注解实现事务控制:
使用注解方式实现声明式事务管理
@Transactional 介绍
@Transactional 注解 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,
该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该
注解来覆盖类级别的定义。
虽然@Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建
议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生
效。另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质
决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,
这将被忽略,也不会抛出任何异常
Spring 基于注解装配 Bean 对象
Spring 基于 Annotation 装配 Bean 对象
在 Spring 中,尽管使用 XML 配置文件可以实现 Bean 的装配工作,但如果应用中Bean 的数量较多,会导致 XML 配置文件过于臃肿,从而给维护和升级带来一定的困难。
在 Spring 框架中提供了一些用于装配 Bean 对象的注解用于替换 xml 文件的中配置。
注册 Bean 对象
3.1@Component
可以使用此注解描述 Spring 中的 Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。
3.2@Service
通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
3.3@Repository
于将数据访问层(DAO 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
3.4@Controller
通常作用在控制层(如 Spring MVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
4 Bean 对象依赖注入注解
4.1@Autowired
用于对 Bean 的属性变量、方法及构造方法进行标注,完成 Bean 的自动注入处理。
@Autowired 按照 Bean 的类型进行装配。
4.2@Resource
其作用与 Autowired 一样。其区别在于 @Autowired 按照 Bean 类型装配,而@Resource 是可以按照 Bean ID 或者类型进行装配。
4.3@Qualifier
与 @Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为按 Bean 的实例名称装配,Bean 的实例名称由 @Qualifier 注解的参数指定。
4.4@Value
可获取 Properties 文件中的值。
5 Spring 配置相关注解
5.1@Configuration
声明当前类为配置类,相当于 xml 形式的 Spring 配置。该注解需要添加到类上。
5.2@Bean
注解在方法上,声明当前方法的返回值为一个 Bean 对象,该对象会被添加 SpringIOC容器中。和标签作用的相同。Bean 的实例名称由 @Qualifier 注解的参数指定。
Junit
Junit 是 Java 编程语言的单元测试框架,用于编写和运行可重复的自动化测试。
单元测试(Unit Testing),是指对软件中的最小可测试单元进行检查和验证。对于单元
测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如 C 语言中单元指一个
函数,Java 里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单
元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的
测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。
Junit 特点:
Junit 是一个开放的资源框架,用于编写和运行测试。
提供注解来识别测试方法。
提供断言来测试预期结果。
Junit 测试允许你编写代码更快,并能提高质量。
Junit 优雅简洁。没那么复杂,花费时间较少。
Junit 测试可以被组织为测试套件,包含测试用例,甚至其他的测试套件。
Junit 在一个条中显示进度。如果运行良好则是绿色;如果运行失败,则变成红色。