一、Spring概述
1. Spring家族
- 官网:https://spring.io
- Spring发展到今天已经形成了一种开发的生态圈,Spring提供了若干个项目,每个项目用于完成特定的功能。
2. Spring体系结构
⑴. Spring Framework系统架构图
Spring Framework是Spring生态圈中最基础的项目,是其他项目的根基
⑵. Spring Framework 学习路线
3. Spring核心概念
⑴. 目前我们代码存在的问题
- 代码书写现状:耦合度偏高
- 解决方案:使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象
⑵. 核心概念
IOC(Inversion of Control)控制反转:
使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。通俗的讲就是 将new对象的权利交给Spring,我们从Spring中获取对象使用即可
Spring技术对IoC思想进行了实现:
- Spring提供了一个容器,称为IOC容器,用来充当IoC思想中的“外部”
- IOC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
DI(Dependency Injection)依赖注入:
在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。
目标:
- 充分解耦
- 使用IoC容器管理bean(IOC)
- 在IoC容器内将有依赖关系的bean进行关系绑定(DI)
最终效果: 使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
二、IOC和DI入门案例
Gitee仓库: https://gitee.com/yuan0_0/spring_frame_quick-start.git
1. 思路分析
- 管理什么?(Service与Dao)
- 如何将被管理的对象告知IOC容器?(配置文件)
- 被管理的对象交给IOC容器,如何获取到IoC容器?(接口)
- IOC容器得到后,如何从容器中获取bean?(接口方法)
- 使用Spring导入哪些坐标?(pom.xml)
实现步骤:
【第一步】导入Spring坐标
【第二步】定义Spring管理的类(接口)
【第三步】创建Spring配置文件,配置对应类作为Spring管理的bean对象
【第四步】初始化IOC容器(Spring核心容器/Spring容器),通过容器获取bean对象
2. 搭建示例项目
⑴. 创建项目
⑵. 服务层
新建 src/main/java/com/it/service/BookService.java
文件:
public interface BookService {
public void save();
}
⑶. 服务处实现类
新建 src/main/java/com/it/service/impl/BookServiceImpl.java
文件:
public class BookServiceImpl implements BookService {
private BookDao bookDao = new BookDaoImpl();
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
⑷. 数据层
新建 src/main/java/com/it/dao/BookDao.java
文件:
public interface BookDao {
public void save();
}
⑸. 数据层实现类
新建 src/main/java/com/it/dao/impl/BookDaoImpl.java
文件:
public class BookDaoImpl implements BookDao {
public void save() {
System.out.println("book dao save ...");
}
}
⑹. 测试类
新建 src/main/java/com/it/App.java
文件:
public class App {
public static void main(String[] args) {
BookService bookService = new BookServiceImpl();
bookService.save();
}
}
3. IOC入门案例
⑴. 导入Spring坐标
编辑 pom.xml
文件:
<dependencies>
<!--导入spring的坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
⑵. Spring配置文件
新建 src/main/resources/applicationContext.xml
文件:
<?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标签标示配置bean
id属性标示给bean起名字
class属性表示给bean定义类型
-->
<bean id="bookDao" class="com.it.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.it.service.impl.BookServiceImpl"/>
</beans>
⑶. 初始化IOC容器
新建src/main/java/com/it/App2.java
文件:
public class App2 {
public static void main(String[] args) {
// 1.创建IoC容器对象,加载spring核心配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.从IOC容器中获取Bean对象(bookDao对象)
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
// 3.调用Bean对象(bookDao对象)的方法
bookDao.save();
System.out.println("-----");
BookService bookService = (BookService) ctx.getBean("bookService");
bookService.save();
}
}
4. DI入门案例
⑴. 思路分析
- 基于IOC管理bean
- Service中使用new形式创建的Dao对象是否保留?(否)
- Service中需要的Dao对象如何进入到Service中?(提供方法)
- Service与Dao间的关系如何描述?(配置)
⑵. 删除使用new的形式创建对象
编辑 src/main/java/com/it/service/impl/BookServiceImpl.java
文件:
public class BookServiceImpl implements BookService {
// private BookDao bookDao = new BookDaoImpl();
// 删除业务层中使用new方式创建的Dao对象
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
}
⑶. 提供依赖对象对应的setter方法
编辑 src/main/java/com/it/service/impl/BookServiceImpl.java
文件:
public class BookServiceImpl implements BookService {
// private BookDao bookDao = new BookDaoImpl();
// 删除业务层中使用new方式创建的Dao对象
private BookDao bookDao;
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
// 提供对应的setter方法
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
}
⑷. 配置service与dao之间的关系
编辑 src/main/resources/applicationContext.xml
文件:
<?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标签标示配置bean
id属性标示给bean起名字
class属性表示给bean定义类型
-->
<bean id="bookDao" class="com.it.dao.impl.BookDaoImpl"/>
<bean id="bookService" class="com.it.service.impl.BookServiceImpl">
<!--配置server与dao的关系
property标签:表示配置当前bean的属性
name属性:表示配置哪一个具体的属性
ref属性:表示参照哪一个bean
-->
<property name="bookDao" ref="bookDao" />
</bean>
</beans>
⑸. 测试结果
⑹. 图解
三、Bean
1. Bean配置
⑴. 基础配置
配置说明:
类别 | 描述 |
---|---|
名称 | bean |
类型 | 标签 |
所属 | beans标签 |
功能 | 定义Spring核心容器管理的对象 |
格式 | <beans><bean/><bean></bean></beans> |
属性列表 | id:bean的id,使用容器可以通过id值获取对应的bean,在一个容器中id值唯一 class:bean的类型,即配置的bean的全路径类名 |
范例 | <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/> <bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"></bean> |
⑵. 别名配置
①. 配置说明
类别 | 描述 |
---|---|
名称 | name |
类型 | 属性 |
所属 | bean标签 |
功能 | 定义bean的别名,可定义多个,使用逗号(,)分号(;)空格( )分隔 |
范例 | <bean id="bookDao" name="dao bookDaoImpl" class="com.itheima.dao.impl.BookDaoImpl"/> <bean name="service,bookServiceImpl" class="com.itheima.service.impl.BookServiceImpl"/> |
②. bean指定别名
编辑 src/main/resources/applicationContext.xml
文件:
<?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标签标示配置bean
id属性标示给bean起名字
class属性表示给bean定义类型
-->
<bean id="bookDao" class="com.it.dao.impl.BookDaoImpl"/>
<!--<bean id="bookService" class="com.it.service.impl.BookServiceImpl">-->
<!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
<bean id="bookService" name="service service4 bookEbi" class="com.it.service.impl.BookServiceImpl">
<!--配置server与dao的关系
property标签:表示配置当前bean的属性
name属性:表示配置哪一个具体的属性
ref属性:表示参照哪一个bean
-->
<property name="bookDao" ref="bookDao" />
</bean>
</beans>
③. 测试类
新建 src/main/java/com/it/AppForName.java
文件:
public class AppForName {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookService bookService = (BookService) ctx.getBean("service");
bookService.save();
}
}
⑶. 作用范围配置
①. 配置说明
类别 | 描述 |
---|---|
名称 | scope |
类型 | 属性 |
所属 | bean标签 |
功能 | 定义bean的作用范围,可选范围如下:singleton 单例(默认)、prototype 非单例 |
范例 | <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype" /> |
②. bean指定作用范围
编辑 src/main/resources/applicationContext.xml
文件:
<?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="com.it.service.impl.BookServiceImpl">-->
<!--name:为bean指定别名,别名可以有多个,使用逗号,分号,空格进行分隔-->
<bean id="bookService" name="service service4 bookEbi" class="com.it.service.impl.BookServiceImpl">
<!--配置server与dao的关系
property标签:表示配置当前bean的属性
name属性:表示配置哪一个具体的属性
ref属性:表示参照哪一个bean
-->
<property name="bookDao" ref="bookDao" />
</bean>
<!--
bean标签标示配置bean
id属性标示给bean起名字
class属性表示给bean定义类型
-->
<!--<bean id="bookDao" class="com.it.dao.impl.BookDaoImpl"/>-->
<!--scope:为bean设置作用范围,可选值为单例singloton,非单例prototype-->
<bean id="bookDao" class="com.it.dao.impl.BookDaoImpl" scope="prototype"/>
</beans>
③. 测试类
新建 src/main/java/com/it/AppForScope.java
文件:
public class AppForScope {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
BookDao bookDao2 = (BookDao) ctx.getBean("bookDao");
System.out.println(bookDao1);
// => com.it.dao.impl.BookDaoImpl@25bbe1b6
System.out.println(bookDao2);
// => com.it.dao.impl.BookDaoImpl@5702b3b1
}
}
④. 说明
在我们的实际开发当中,绝大部分的Bean是单例的,也就是说绝大部分Bean不需要配置scope属性
- 适合交给容器进行管理的bean: 表现层对象、业务层对象、数据层对象、工具对象
- 不适合交给容器进行管理的bean: 封装实体的域对象
2. Bean实例化
bean本质上就是对象,创建bean使用构造方法完成
Gitee仓库: https://gitee.com/yuan0_0/spring_frame_bean_instance.git
⑴. 构造方法(常用)
①. 创建项目
②. spring坐标
编辑 pom.xml
文件:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>spring_01_bean_instance</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
</project>
③. 接口
新建 src/main/java/com/it/dao/BookDao.java
文件:
public interface BookDao {
public void save();
}
④. 接口实现类
新建 src/main/java/com/it/dao/impl/BookDaoImpl.java
文件:
public class BookDaoImpl implements BookDao {
// 创建无参构造方法
public BookDaoImpl() {
System.out.println("book dao constructor is running ....");
}
public void save() {
System.out.println("book dao save ...");
}
}
⑤. 配置文件
新建 src/main/resources/applicationContext.xml
文件:
<?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-->
<bean id="bookDao" class="com.it.dao.impl.BookDaoImpl"/>
</beans>
⑥. 测试类
新建 src/main/java/com/it/AppForInstanceBook.java
文件:
public class AppForInstanceBook {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}
无参构造方法如果不存在,将抛出异常
BeanCreationException
⑵. 静态工厂(了解)
①. 接口
新建 src/main/java/com/it/dao/OrderDao.java
文件:
public interface OrderDao {
public void save();
}
②. 实现类
新建 src/main/java/com/it/dao/impl/OrderDaoImpl.java
文件:
public class OrderDaoImpl implements OrderDao {
public void save() {
System.out.println("order dao save ...");
}
}
③. 静态工厂
新建 src/main/java/com/it/factory/OrderDaoFactory.java
文件:
//静态工厂创建对象
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
System.out.println("factory setup....");
return new OrderDaoImpl();
}
}
④. 配置
新建 src/main/resources/applicationContext.xml
文件:
<?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-->
<!--<bean id="bookDao" class="com.it.dao.impl.BookDaoImpl"/>-->
<!--方式二:使用静态工厂实例化bean-->
<bean id="orderDao" class="com.it.factory.OrderDaoFactory" factory-method="getOrderDao"/>
</beans>
⑤. 测试类
新建 src/main/java/com/it/AppForInstanceOrder.java
文件:
public class AppForInstanceOrder {
public static void main(String[] args) {
//通过静态工厂创建对象
OrderDao orderDao = OrderDaoFactory.getOrderDao();
orderDao.save();
}
}
⑶. 实例化工厂(了解)
①. 接口
新建 src/main/java/com/it/dao/UserDao.java
文件:
public interface UserDao {
public void save();
}
②. 实现类
新建 src/main/java/com/it/dao/impl/UserDaoImpl.java
文件:
public class UserDaoImpl implements UserDao {
public void save() {
System.out.println("user dao save ...");
}
}
③. 实例化工厂
新建 src/main/java/com/it/factory/UserDaoFactory.java
文件:
//实例工厂创建对象
public class UserDaoFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
④. 测试类
新建 src/main/java/com/it/AppForInstanceUser.java
文件:
public class AppForInstanceUser {
public static void main(String[] args) {
//创建实例工厂对象
UserDaoFactory userDaoFactory = new UserDaoFactory();
//通过实例工厂对象创建对象
UserDao userDao = userDaoFactory.getUserDao();
userDao.save();
}
}
⑤. 配置
新建 src/main/resources/applicationContext.xml
文件:
<?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-->
<!--<bean id="bookDao" class="com.it.dao.impl.BookDaoImpl"/>-->
<!--方式二:使用静态工厂实例化bean-->
<!--<bean id="orderDao" class="com.it.factory.OrderDaoFactory" factory-method="getOrderDao"/>-->
<!--方式三:使用实例工厂实例化bean-->
<bean id="userFactory" class="com.it.factory.UserDaoFactory"/>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
</beans>
⑥. 测试类
新建 src/main/java/com/it/AppForInstanceUser.java
文件:
public class AppForInstanceUser {
public static void main(String[] args) {
// //创建实例工厂对象
// UserDaoFactory userDaoFactory = new UserDaoFactory();
// //通过实例工厂对象创建对象
// UserDao userDao = userDaoFactory.getUserDao();
// userDao.save();
// 实例化工厂
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) ctx.getBean("userDao");
userDao.save();
}
}
⑷. FactoryBean(实用)
①. FactoryBean
新建 src/main/java/com/it/factory/UserDaoFactoryBean.java
文件:
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//代替原始实例工厂中创建对象的方法
// bean实例
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
// bean类型
public Class<?> getObjectType() {
return UserDao.class;
}
// bean作用范围: 单例
public boolean isSingleton() {
return true;
}
}
②. 配置
编辑 src/main/resources/applicationContext.xml
文件:
<?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-->
<!--<bean id="bookDao" class="com.it.dao.impl.BookDaoImpl"/>-->
<!--方式二:使用静态工厂实例化bean-->
<!--<bean id="orderDao" class="com.it.factory.OrderDaoFactory" factory-method="getOrderDao"/>-->
<!--方式三:使用实例工厂实例化bean-->
<!--<bean id="userFactory" class="com.it.factory.UserDaoFactory"/>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>-->
<!--方式四:使用FactoryBean实例化bean-->
<bean id="userDao" class="com.it.factory.UserDaoFactoryBean"/>
</beans>
③. 测试类
编辑 src/main/java/com/it/AppForInstanceUser.java
文件:
public class AppForInstanceUser {
public static void main(String[] args) {
// //创建实例工厂对象
// UserDaoFactory userDaoFactory = new UserDaoFactory();
// //通过实例工厂对象创建对象
// UserDao userDao = userDaoFactory.getUserDao();
// userDao.save();
// 实例化工厂
// ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// UserDao userDao = (UserDao) ctx.getBean("userDao");
// userDao.save();
// 测试bean作用范围: 单例/非单例
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) ctx.getBean("userDao");
UserDao userDao2 = (UserDao) ctx.getBean("userDao");
System.out.println(userDao1);
System.out.println(userDao2);
}
}