文章目录
- Spring简介
- Spring课程介绍
- 为什么要学
- 学什么
- 怎么学
- 初识Spring
- Spring家族
- Spring发展史
- Spring体系结构
- Spring核心概念
- 目前代码存在的问题
- 核心概念
- IOC和DI入门案例
- IOC入门案例
- 入门案例分析
- 实现步骤
- 实现代码
- DI入门案例
- DI入门案例分析
- 实现步骤
- 实现代码
- 图解演示
- Bean的基础配置
- bean基础配置
- id
- class
- bean别名配置
- name
- bean作用范围配置
- scope
- Bean的实例化
- bean是如何创建的
- 实例化bean的三种方式
- 构造方法方式(重点)
- 静态工厂方式(了解)
- 实例工厂方式(了解)
- 实现FactoryBean<T>方式(扩展,了解)
- 依赖注入
- 依赖注入方式
- setter注入
- 构造器注入(了解)
- 方式选择
- 依赖自动装配
- 集合注入
- Bean的生命周期
- 生命周期相关概念介绍
- bean的生命周期
- 初始化容器
- 使用bean
- 关闭/销毁容器
- 代码演示
- bean生命周期演示
- bean生命周期控制--接口控制(了解)
- bean销毁时机
Spring简介
Spring课程介绍
为什么要学
- Spring技术是JavaEE开发必备技能,企业开发技术选型命中率>=90%
- 专业角度
- 简化开发,降低企业级开发的复杂性
- 框架整合,高效整合其他技术,提高企业级应用开发与运行效率
学什么
- 简化开发
- IOC
- AOP(面向切面编程)
- 事务处理
- 事务处理
怎么学
- 学习Spring框架设计思想
- 学习基本操作,思考操作与思想间的联系
- 学习案例,熟悉应用操作的同时,体会思想
初识Spring
Spring家族
- 官网(中文):https://spring.p2hp.com/index.html
- Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能
Spring发展史
Spring体系结构
4.0
Spring核心概念
目前代码存在的问题
在不同的类中使用对象得先new对象,然后再进行使用
另外接口中要是实现类变量,等号右边也得改变
问题:这样耦合度偏高
解决方案:使用对象时,在程序中不要主动new对象,转换为由外部提供对象
核心概念
- IOC(Inversion of Control)控制反转
使用对象时,由主动new产生对象转换为由外部提对 象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。
- Spring对Ioc思想进行了实现
- Spring提供了一个容器,称为IOC容器,用来充当Ioc思想中的"外部"
- IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在Ioc容器中统称为Bean
- DI(Dependency Injection)依赖注入
- 在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入
- 目标:充分解耦
- 使用Ioc容器管理bean
- 在Ioc容器内将有依赖关系的bean进行关系绑定
- 最终效果
- 使用对象时不仅可以直接从Ioc容器中获取,并且获取到的bean已经绑定了所有的依赖关系
- 使用对象时不仅可以直接从Ioc容器中获取,并且获取到的bean已经绑定了所有的依赖关系
IOC和DI入门案例
IOC入门案例
入门案例分析
- 管理什么?(Service与Dao)
- 如何将被管理的对象告知IOC容器?(配置文件)
- 被管理的对象交给IOC容器,如何获取到IoC容器?(接口)
- IOC容器得到后,如何从容器中获取bean?(接口方法)
- 使用Spring导入哪些坐标?(pom.xml)
实现步骤
- 导入Spring坐标
- 定义Spring管理的类(接口)
- 创建Spring配置文件,配置对应类作为Spring管理的bean对象
- 初始化IOC容器(Spring核心容器/Spring容器),通过容器获取bean
实现代码
- 坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
- 定义接口
//接口
public interface BookService {
void save();
}
//实现类
public class BookServiceImpl implements BookService{
@Override
public void save() {
System.out.println("BookService save...");
}
}
- 创建配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bookService" class="org.example.service.BookServiceImpl"></bean>
</beans>
注:bean定义id属性在同一个上下文中(IOC容器中)不能重复
- 初始化ioc容器,通过容器获取bean对象
public class App {
public static void main( String[] args ) {
//1.创建IOC容器,加载Spring核心配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.从IOC容器中获取bean对象(BookService对象)
BookService bookService = (BookService) ctx.getBean("bookService");
//3.调用Bean对象(BookService)的方法
bookService.save();
}
}
DI入门案例
DI入门案例分析
- 基于IOC管理bean
- Service中使用new形式创建的Dao对象是否保留?(否)
- Service中需要的Dao对象如何进入到Service中?(提供set方法)
- Service与Dao间的关系如何描述?(配置)
实现步骤
- 删除使用new的形式创建对象的代码
- 提供依赖对象对应的setter方法
- 配置service与dao之间的关系
实现代码
- 先创建BookDao接口以及实现类
public interface BookDao {
void save();
}
public class BookDaoImpl implements BookDao{
@Override
public void save() {
System.out.println("BookDao save...");
}
}
- 在BookService的接口和实现类中提供依赖对象对应的setter方法
public interface BookService {
void save();
void setBookDao(BookDao bookDao);
}
public class BookServiceImpl implements BookService{
private BookDao bookDao;
@Override
public void save() {
System.out.println("BookService save...");
}
@Override
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
- 在配置文件中配置service和dao的关系
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="bookService" class="org.example.service.BookServiceImpl">
<property name="bookDao" ref="bookDao"></property>
</bean>
<bean id="bookDao" class="org.example.dao.BookDaoImpl"></bean>
</beans>
图解演示
Bean的基础配置
bean基础配置
id
使用容器通过id值获取对应的bean,在一个容器中id值唯一
class
bean的类型,即配置bean的全路径类名(实体类)
bean别名配置
name
定义bean的别名,可定义多个,使用逗号,空格,分号隔开
在通过applicationContext获取bean时,也可以通过别名获取
bean作用范围配置
scope
定义bean的作用范围
- singleton:单例(默认)
- prototype:非单例
扩展:scope的取值不仅仅只有singleton和prototype,还有request、session、application、 websocket ,表示创建出的对象放置在web容器(tomcat)对应的位置。比如:request表示保存到request域中。
Bean的实例化
bean是如何创建的
bean本质上就是对象,创建bean使用构造方法完成
实例化bean的三种方式
构造方法方式(重点)
- BookDaoImpl实现类
public class BookDaoImpl implements BookDao{
public BookDaoImpl(){
System.out.println("bookDaoImpl 无参构造...");
}
@Override
public void save() {
System.out.println("BookDao save...");
}
}
- 配置文件
<bean id="bookDao" class="org.example.dao.BookDaoImpl"></bean>
- main方法
//1.创建IOC容器,加载Spring核心配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.从IOC容器中获取bean对象(BookService对象)
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
//3.调用Bean对象(BookService)的方法
bookDao.save();
- 运行结果
说明默认使用是无参构造方法
注:无参构造方法如果不存在,会报错
静态工厂方式(了解)
- 删除BookDao实现类的无参构造方法
- 创建一个类书写静态工厂的代码
public class StaticFactory {
public static BookDao getBookDao(){
System.out.println("静态工厂...");
return new BookDaoImpl();
}
}
- 配置文件(将之前的注释掉或删掉)
<bean id="staticFactory" class="org.example.factory.StaticFactory" factory-method="getBookDao"></bean>
实例工厂方式(了解)
- 创建一个类书写实例工厂的代码
- 配置文件(之前的注释掉)
<bean id="InstanceDaoFactory" class="org.example.factory.InstanceFactory" ></bean>
<bean id="bookDao" factory-bean="InstanceDaoFactory" factory-method="getBookDao"></bean>
实现FactoryBean方式(扩展,了解)
实例化工厂的一种方式
- 书写类实现FactoryBean
public class BookDaoFactory implements FactoryBean {
@Override
//代替原始实例工厂中创建对象的方法
public Object getObject() throws Exception {
System.out.println("FactoryBean ...");
return new BookDaoImpl();
}
@Override
public Class<?> getObjectType() {
return BookDao.class;
}
}
- 配置文件
<bean id="bookDao" class="org.example.factory.BookDaoFactory"></bean>
依赖注入
依赖注入方式
setter注入
要先提供对应的set方法
- 引用类型
配置文件中property标签ref属性注入引用类型对象
- 简单类型
配置文件中property标签value属性注入引用类型对象
构造器注入(了解)
要先书写对应的构造方法
- 引用类型
配置文件中constructor-arg标签ref属性注入引用类型对象
- 简单类型
配置文件中constructor-arg标签value属性注入引用类型对象
- 参数适配
也可以使用constructor-arg标签中type属性按形参类型注入或index属性按形参位置注入
方式选择
自己开发的模块推荐使用setter方式注入,如果受控对象没有提供setter方法就必须使用构造器注入
依赖自动装配
配置中使用bean标签的autowire属性设置自动装配的类型
使用按类型装配,必须保障容器中相同类型的bean唯一
<bean id="bookService" class="org.example.service.BookServiceImpl" autowire="byType">
<!-- <property name="bookDao" ref="bookDao"></property>-->
</bean>
<bean id="bookDao" class="org.example.dao.BookDaoImpl"></bean>
集合注入
注入数据类型,List类型,Set类型,Map类型,Properties类型
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
说明:property标签标识setter注入,构造方式注入constructor-arg标签内部也可以写<array>、<list>、<set>、<map>、<props>标签
Bean的生命周期
生命周期相关概念介绍
- 生命周期:从创建到消亡的完整过程
- bean生命周期:bean从创建到销毁的整体过程
- bean生命周期控制:在bean创建后到销毁前做一些事情
bean的生命周期
初始化容器
- 创建对象
- 执行构造方法
- 执行属性注入(set注入)
- 执行bean初始化方法
使用bean
- 执行业务操作
关闭/销毁容器
- 执行bean销毁方法
代码演示
bean生命周期演示
- 提供生命周期控制方法
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
//表示bean初始化对应的操作
public void init(){
System.out.println("init...");
}
//表示bean销毁前对应的操作
public void destory(){
System.out.println("destory...");
}
}
- 配置文件
<!--init-method:设置bean初始化生命周期回调函数,此处填写init方法名-->
<!--destroy-method:设置bean销毁生命周期回调函数,仅适用于单例对象,此处填写destory方法名-->
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init" destroy-method="destory"/>
- 测试类
public class AppForLifeCycle {
public static void main( String[] args ) {
//此处需要使用实现类类型,接口类型没有close方法
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
//关闭容器,执行销毁的方法
ctx.close();
}
}
bean生命周期控制–接口控制(了解)
- 实现InitializingBean, DisposableBean接口
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
System.out.println("set .....");
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
public void destroy() throws Exception {
System.out.println("service destroy");
}
public void afterPropertiesSet() throws Exception {
System.out.println("service init");
}
}
- 不需要在配置文件中bean标签中写init-method属性和destory-method属性
bean销毁时机
- 容器关闭前触发bean的销毁
- 关闭容器的方式
- 手工关闭容器
ConfigurableApplicationContext接口**close()**操作
- 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机
ConfigurableApplicationContext接口**registerShutdownHook()**操作
public class AppForLifeCycle {
public static void main( String[] args ) {
//此处需要使用实现类类型,接口类型没有close方法
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
//注册关闭钩子函数,在虚拟机退出之前回调此函数,关闭容器
ctx.registerShutdownHook();
//关闭容器
//ctx.close();
}
}