目录
一、Spring系统架构和学习路线
二、Spring核心概念
2.1 IOC、IOC容器、Bean、DI
2.1.1 IOC(Inversion of Control)控制反转
2.1.2 DI(Dependency Injection)依赖注入
2.2 核心概念小结
三、入门案例
3.1 IOC入门案例
3.2 DI入门案例
3.3 IOC相关内容——Bean
3.3.1 Bean的基础配置
3.3.2 Bean的实例化
3.4 DI相关内容——DI依赖注入
3.4.1 Setter注入
3.4.2 构造器注入(*)
3.4.3 自动配置(*)
3.4.4 集合注入
一、Spring系统架构和学习路线
Spring Framework的5版本目前没有最新的架构图,而最新的是4版本,所以接下来主要研究的是4的架构图。
学习路线:
二、Spring核心概念
使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象 |
2.1 IOC、IOC容器、Bean、DI
2.1.1 IOC(Inversion of Control)控制反转
- 控制反转:使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部。
-
Spring 提供了一个容器,称为 IOC 容器 ,用来充当 IOC 思想中的 " 外部",IOC 思想中的 别人 [ 外部 ] 指的就是 Spring 的 IOC 容器。
-
IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象,被创建或被管理的对象在 IOC 容器中统称为 Bean , IOC 容器中放的就是一个个的 Bean 对象。
-
当 IOC 容器中创建好 service 和 dao对象后,程序还不能正确执行,因为 service 运行需要依赖 dao对象,但是 service 对象和 dao对象没有任何关系,也就是说要绑定 service 和 dao对象之间的关系,绑定关系就要用到 DI。
2.1.2 DI(Dependency Injection)依赖注入
- 依赖注入:在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入(业务层要用数据层的类对象,以前是自己new的,现在自己不new了,靠别人[外部其实指的就是IOC容器]来给注入进来)
2.2 核心概念小结
介绍完Spring的IOC和DI的概念后,我们会发现这两个概念的最终目标就是:充分解耦,具体实现靠:
|
三、入门案例
3.1 IOC入门案例
***理解原理,实际开发不会用到!***
分析 |
(1)Spring
是使用容器来管理
bean
对象的,那么管什么
?
主要管理项目中所使用到的类对象,比如(Service和Dao)
(2)
如何将被管理的对象告知
IOC
容器
?
使用配置文件
(3)
被管理的对象交给
IOC
容器,要想从容器中获取对象,就先得思考如何获取到
IOC
容器
?
Spring框架提供相应的接口
(4)IOC
容器得到后,如何从容器中获取
bean?
调用Spring框架提供对应接口中的方法
|
具体步骤 | |
实现 |
步骤1:创建Maven项目
步骤2:添加Spring依赖的jar包 步骤3:添加案例中需要的 创建BookService,BookServiceImpl,BookDao和BookDaoImpl四个类 步骤4:添加spring配置文件 resources下添加spring配置文件applicationContext.xml,并完成bean的配置 步骤5:在配置文件中完成bean的配置 步骤6:获取IOC容器 步骤7:从容器中获取对象进行方法调用 步骤8:运行程序 |
3.2 DI入门案例
***理解原理,实际开发不会用到!***
分析 |
|
具体步骤 | |
实现 |
步骤
1:
去除代码中的
new
在
BookServiceImpl
类中,删除业务层中使用
new
的方式创建的
dao
对象
步骤
2:
为属性提供
setter
方法
在
BookServiceImpl
类中
,
为
BookDao
提供
setter
方法
步骤
3:
修改配置完成注入
注意:两个bookDao含义不同,差别如图:
步骤
4:
运行程序
|
3.3 IOC相关内容——Bean
***理解原理,实际开发不会用到配置文件,更多使用注解开发!***
3.3.1 Bean的基础配置
Bean的id与class属性
<bean id="" class=""/>
id: bean的id,使用容器可以通过id值获取对应的bean,在一个容器中id值唯一
class: bean的类型,即配置的bean的全路径类名
Bean的name属性
定义bean的别名,可定义多个,使用逗号(,)分号(;)空格( )分隔,例如:
<bean id="bookService" name="service service4 bookEbi"
class="com.itheima.service.impl.BookServiceImpl">
Bean的scope配置
(1)单例(默认)——singleton
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" scope="singleton"/>
单例的意思就是,同一个bean获取两次,将对象打印到控制台,打印出的地址值完全一致。
默认bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高。
(2)非单例——prototype
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>
总结
- 表现层对象
- 业务层对象
- 数据层对象
- 工具对象
- 封装实例的域对象,因为会引发线程安全问题,所以不适合
3.3.2 Bean的实例化
第一种:构造方法实例化(常用)
结论:Spring底层使用的是类的无参构造方法,并且能访问到类中的私有构造方法,显而易见,Spring底层用的是反射
第二种:静态工厂实例化(*)
第三种:FactoryBean(实用)
-
准备一个 UserDao 和UserDaoImpl类
-
创建一个 UserDaoFactoryBean 的类,实现FactoryBean接口,重写接口的方法
-
在 Spring 的配置文件中进行配置
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
-
创建一个运行类AppForInstanceUser
-
运行
public boolean isSingleton() {
return false;
}
3.4 DI相关内容——DI依赖注入
***理解原理,实际开发使用的是注解开发!***
3.4.1 Setter注入
- 对于引用数据类型使用的是<property name=" " ref=" "/>
- 对于简单数据类型使用的是<property name=" " value=" "/>
(1)引用类型注入
上面的例子就是引用类型注入,例如现在有BookDao,UserDao接口(不再赘述),有BookServiceImpl实现类,代码如下:
public class BookServiceImpl implements BookService {
private BookDao bookDao;
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
userDao.save();
}
}
现在,我们在配置文件中使用property标签注入
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
<property name="userDao" ref="userDao"/>
</bean>
(2)简单类型注入
BookDaoImpl实现类如下:
public class BookDaoImpl implements BookDao {
private String databaseName;
private int connectionNum;
public void setConnectionNum(int connectionNum) {
this.connectionNum = connectionNum;
}
public void setDatabaseName(String databaseName) {
this.databaseName = databaseName;
}
public void save() {
System.out.println("book dao save
..."+databaseName+", "+connectionNum);
}
}
现在,我们在配置文件中使用property标签注入
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<property name="databaseName" value="mysql"/>
<property name="connectionNum" value="10"/>
</bean>
<bean id="userDao" class="com.itheima.dao.impl.UserDaoImpl"/>
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
<property name="userDao" ref="userDao"/>
</bean>
3.4.2 构造器注入(*)
- 引用数据类型 <constructor-arg name="" index="" type="" ref=""/>
- 简单数据类型 <constructor-arg name="" index="" type="" value=""/>
实际开发中,更推荐使用Setter注入,故构造器注入略
3.4.3 自动配置(*)
方式:
-
按类型(常用)
-
按名称
-
按构造方法
-
不启用自动装配
略
3.4.4 集合注入
在BookDaoImpl实现类中,不再是引用类型和简单数据类型,而是集合类型,常见的集合类型有:
-
数组
- List
- Set
- Map
- Properties
在配置文件中,注入数组数据类型如下:
<property name="array">
<array>
<value>100</value>
<value>200</value>
<value>300</value>
</array>
</property>
其他略
笔记跟课:
https://www.bilibili.com/video/BV1Fi4y1S7ix/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=0e0517ebadf244dd640ab0b61dd700c5https://www.bilibili.com/video/BV1Fi4y1S7ix/?spm_id_from=333.1007.top_right_bar_window_custom_collection.content.click&vd_source=0e0517ebadf244dd640ab0b61dd700c5