一、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的概念后,我们会发现这两个概念的最终目标就是:充分解耦,具体实现靠:
- 使用IOC容器管理bean(IOC)
- 在IOC容器内将有依赖关系的bean进行关系绑定(DI)
- 最终结果为:使用对象时不仅可以直接从IOC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
三、入门案例
3.1 、IOC入门案例
***理解原理,实际开发不会用到!***1 |
---|
分析 | (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 |
---|
分析 | 1、要想实现依赖注入,必须要基于IOC管理Bean 2、Service中使用new形式创建的Dao对象需要删除掉,最终要使用IOC容器中的bean对象 3、Service 中需要的 Dao 对象如何进入到 Service 中? 在 Service中提供方法,让Spring的IOC容器可以通过该方法传入bean对象 4、Service 与 Dao 间的关系如何描述? 使用配置文件 |
具体步骤 | |
实现 | 步骤 1: 去除代码中的 new 在 BookServiceImpl 类中,删除业务层中使用 new 的方式创建的 dao 对象 步骤 2: 为属性提供 setter 方法 在 BookServiceImpl 类中 , 为 BookDao 提供 setter 方法 步骤 3: 修改配置完成注入 注意:两个bookDao含义不同,差别如图: 步骤 4: 运行程序 |
3.3 、IOC相关内容——Bean
***理解原理,实际开发不会用到配置文件,更多使用注解开发!***1 |
---|
3.3.1 Bean的基础配置
1、Bean的id与class属性
<bean id="" class=""/>
-
id: bean的id,使用容器可以通过id值获取对应的bean,在一个容器中id值唯一
-
class: bean的类型,即配置的bean的全路径类名
2、Bean的name属性
3、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"/>
总结
哪些 bean 对象适合交给容器进行管理(即单例) ?
- 表现层对象
- 业务层对象
- 数据层对象
- 工具对象
哪些 bean 对象不适合交给容器进行管理(即非单例) ? - 封装实例的域对象,因为会引发线程安全问题,所以不适合
3.3.2 Bean的实例化
- 第一种:构造方法实例化(常用)
结论:Spring底层使用的是类的无参构造方法,并且能访问到类中的私有构造方法,显而易见,Spring底层用的是反射
-
第二种:静态工厂实例化(*)
-
第三种:FactoryBean(实用)
1、准备一个 UserDao 和UserDaoImpl类
2、创建一个 UserDaoFactoryBean 的类,实现FactoryBean接口,重写接口的方法
3、在 Spring 的配置文件中进行配置
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
4、创建一个运行类AppForInstanceUser
5、运行
注意:该方法设置的对象默认也为单例,单例/非单例的具体实现如下:
在UserFactoryBean类中实现接口中的方法isSingleton():
public boolean isSingleton() {
return false;
}
3.4 DI相关内容——DI依赖注入
***理解原理,实际开发不会用到配置文件,更多使用注解开发!***1 |
---|
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://blog.csdn.net/qq_45832961/article/details/129015631