Spring简介
Spring是什么
Spring是分层的Java SE/EE应用full-stack轻量级开源框架,以IoC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核。
提供了展现层 SpringMVC 和持久层 Spring JDBCTemplate 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的Java EE 企业应用开源框架。
Spring的优势
- 方便解耦,简化开发
- 通过 Spring 提供的IoC容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
- AOP 编程的支持
- 通过 Spring的 AOP 功能,方便进行面向切面编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松实现。
- 声明式事务的支持
- 可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务管理,提高开发效率和质量。
- 方便程序的测试
- 可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情
- 方便集成各种优秀框架
- Spring对各种优秀框架(Struts、Hibernate、Hessian、Quartz等)的支持。
- 降低 JavaEE API 的使用难度
- Spring对 JavaEE API(如 JDBC、JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的使用难度大为降低。
- Java 源码是经典学习范例
- Spring的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对Java 设计模式灵活运用以及对 Java技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。
Spring的体系结构
Spring入门
Spring程序开发步骤
之前开发是在业务层调用DAO层来new
对象,现在借助Spring框架来实现解耦合:先将DAO配置到xml
文件中,然后通过Spring框架来读取xml
配置文件,最后在业务层通过Spring提供的API来得到对象。
简而言之,就是将对象的创建权交给了Spring。
- 导入 Spring 框架对应的jar包
- 编写 Dao 接口和实现类
- 创建 xml 配置文件
- 在 xml 配置文件中配置 UserDaoImpl
- 使用 Spring 的 API 获得 Bean 实例
解耦的意义:当业务对象改变时,只需要改变xml
配置文件,而不需要修改业务层代码
使用IDEA实现Sping解耦
创建javaweb项目
借助Maven来进行项目构建和依赖管理。不会使用Maven的小伙伴,可以看我之前的Maven笔记:传送门
这里不做赘述
导入Spring框架对应的jar包
借助Maven来进行依赖管理,在pom.xml
文件中写入spring开发的基本包坐标
|
|
编写Dao接口和实现类
在main\java
下新建UserDao
接口类
|
|
在com.wyatt.dao
下新建UserDaoImpl
实现类
|
|
在 xml 配置文件中配置 UserDaoImpl
在main\resources
下新建xml
配置文件,取名叫applicationContext
|
|
使用 Spring 的 API 获得 Bean 实例
在main\java
中新建一个测试类UserDaoDemo
,在该类的方法中使用 Spring 的 API 来获得 Bean 实例
|
|
在控制台可以看到打印save running...
,说明通过Spring框架提供的API调用UserDao
对象的save()
方法成功。
Spring配置文件
Bean标签基本配置
用于将配置对象交由Spring来创建。
默认情况下它调用的是类中的无参构造函数,如果没有无参构造函数则不能创建成功。
基本属性:
id
:Bean实例在Spring容器中的唯一标识class
:Bean的全限定名称
|
|
Bean标签范围配置
scope
:指对象的作用范围,取值如下:
取值范围 | 说明 |
---|---|
singleton | 默认值,单例的 |
prototype | 多例的 |
request | WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中 |
session | WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中 |
global session | WEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当于 session |
验证singleton
在src\test\java
下新建测试类SpringTest
借助junit
来进行单元测试,在pom.xml
中引入junit
的相关依赖
|
|
在SpringTest
测试类中编写一个测试方法test1()
测试singleton
的作用范围
|
|
从控制台的打印结果可以看出,两次getBean()
获得的对象地址相同,是同一个对象。这意味如果Bean
的作用范围配置为singleton
,则在Spring容器中该Bean
对象只有一个。
验证prototype
在xml
配置文件中配置Bean
作用范围为prototype
|
|
上面验证singleton
的代码不变,重新执行
从控制台的打印结果可以看出,两次getBean()
获得的对象地址不同,不是同一个对象。这意味如果Bean
的作用范围配置为prototype
,则在Spring容器中该Bean
对象可以有多个。
小结
当scope的取值为singleton时
-
Bean的实例化个数:1个
-
Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例
-
Bean的生命周期:
-
对象创建:当应用加载,创建容器时,对象就被创建了
-
对象运行:只要容器在,对象一直活着
-
对象销毁:当应用卸载,销毁容器时,对象就被销毁了
-
当scope的取值为prototype时
- Bean的实例化个数:多个
- Bean的实例化时机:当调用
getBean()
方法时实例化Bean- 对象创建:当使用对象时,创建新的对象实例
- 对象运行:只要对象在使用中,就一直活着
- 对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了
Bean生命周期配置
init-method
:指定类中的初始化方法名称destroy-method
:指定类中销毁方法名
Bean实例化三种方式
- 无参构造方法实例化
- 工厂静态方法实例化
- 工厂实例方法实例化
工厂是一个java类,专门用来生产对象
Bean的依赖注入入门
之前的实践都是借助Spring在Dao层产生对象,而在实际开发中,业务层和web层也需要产生对象。
在main\java\com\wyatt
下新建业务层中的UserService
接口
|
|
在main\java\com\wyatt\service
下创建接口的实现类UserServiceImpl
在业务层中通过Spring获取dao层对象,并调用它的save()
方法
|
|
在main\java\com\wyatt\demo
中新建一个模拟web层中的类UserController
在web层调用业务层来获取dao层对象
|
|
更进一步,将业务层的对象也配置到xml
文件中
|
|
在web层借助Spring来获取service层对象,并调用service层对象的getDaoObject()
方法,在service层借助Spring来获取dao层对象,并调用dao层对象的save()
方法
|
|
Bean的依赖注入分析
上例中的UserService实例和UserDao实例都存在于Spring容器中,当前的做法是在容器外部获得UserService实例和UserDao实例,然后在容器外部将Dao组装到Service中。
因为UserService和UserDao都在Spring容器中,而web层最终程序直接使用的是UserService,所以可以在Spring容器中,将UserDao设置到UserService内部。
Bean的依赖注入概念
依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。
在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用dao层的方法。
那这种业务层和dao层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。简单的说,就是坐等框架把dao层对象传入业务层,而不用我们自己去获取。
Bean的依赖注入方式
将UserDao注入到UserService内部
- 构造方法
- set方法
set方法注入
- 在
UserServiceImpl
内部创建一个UserDao
属性,设置该属性的set()
方法。 - 因为在依赖注入后,Spring容器内部会自动把dao层对象传入业务层,而不用我们自己去获取,所以删除业务层手动获取dao对象的语句。
|
|
在xml
配置文件中进行依赖注入,告诉Spring各个对象间的依赖关系
|
|
构造方法注入
在UserServiceImpl
内写一个有参构造方法和一个无参构造方法
|
|
在xml
配置文件中进行依赖注入,告诉Spring各个对象间的依赖关系
|
|
Bean依赖注入的数据类型
上面的操作,都是注入的引用Bean,除了对象的引用可以注入,普通数据类型,集合等都可以在容器中进行注入。
可以注入三种数据类型
- 引用数据类型
- 普通数据类型
- 集合数据类型
之前的操作都是对UserDao
对象的引用进行注入的。下面将以set
方法注入为例,演示普通数据类型和集合数据类型的注入。
普通数据类型的注入
|
|
|
|
集合数据类型的注入
方法大体同上例,不再赘述。具体代码可以在我的GitHub仓库中查看。
引入其他的配置文件
实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import
标签进行加载。
|
|
Spring配置文件小结
|
|
Spring相关API
ApplicationContext的继承体系
|
|
ApplicationContext
:接口类型,代表应用上下文,可以通过其实例获得 Spring 容器中的 Bean 对象
ApplicationContext的三个实现类
ClassPathXmlApplicationContext
:它是从类的根路径下加载配置文件,推荐使用这种。FileSystemXmlApplicationContext
:它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任意位置。AnnotationConfigApplicationContext
:当使用注解配置容器对象时,需要使用此类来创建 spring 容器。它用来读取注解。
getBean方法的使用
|
|