Spring框架的概述以及Spring中基于XML的IOC配置
Spring概述
Spring是什么
- 分层的
Java SE/EE
应用full-stack(全栈)
轻量级开源框架 - 展现层
Spring MVC
、持久层Spring JDBC
以及业务层事务管理
等
Spring的两大核心
IoC
(反转控制)和AOP
(面向切面编程)
Spring优势
- 方便
解耦
,简化开发 AOP
编程的支持声明式事务
的支持- 方便
程序的测试
- 方便
集成各种优秀框架
- 降低
JavaEE
API
的使用难度 - Java
源码
是经典学习范例
Spring体系结构
程序的耦合及解耦
耦合性(Coupling)
,也叫耦合度
,是对模块间关联程度的度量。
在软件工程中,耦合
指的就是就是对象之间的依赖性
。
划分模块的一个准则就是高内聚低耦合
。
- 内容耦合
- 公共耦合
- 外部耦合
- 控制耦合
- 标记耦合
- 数据耦合
- 非直接耦合
解耦思路
编译期不依赖,运行时才依赖
- 使用反射创建对象,而避免使用new关键字
- 通过读取配置文件来获取要创建的对象全限定类名
工厂模式解耦
工厂:读取配置文件,创建和获取三层对象的类
把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,把这些对象创建出来 并存起来。在接下来的使用的时候,直接拿过来用就好了。
单例对象
单例对象:只创建一次,从而类中的成员也就只会初始化一次
多例对象:对象被创建多次,执行效率没有单例对象高
newInstance----每次都会调用默认构造函数创建对象
为实现单例,创建的对象需要存起来,否则长时间未调用会被Java回收机制
处理掉
问题:存到哪?用什么存?
定义一个Map
,用于存放我们要创建的对象。我们把它称之为容器
。
有了容器后,在工厂
类中,不仅要实例化对象
,也需要实例化容器
。
- 取出配置文件中的所有key
遍历枚举
取出每个key
及对应value(beanPath)
- 再通过
反射创建对象
- 再把
key和value(实例化的对象)
存入到容器
中
这样就可以根据bean的名称获取单例对象了
IoC概念和Spring中的IoC
控制反转(Inversion of Control
,缩写为IoC
),是面向对象编程中的一种设计原则
,可以用来减低
计算机代码之间的耦合度
。其中最常见的方式叫做依赖注入(Dependency Injection
,简称DI
),还有一种方式叫“依赖查找”(Dependency Lookup
)。
通过控制反转,对象在被创建的时候,由一个调控系统内所有对象
的外界实体
将其所依赖的对象的引用
传递给它。也可以说,依赖被注入到对象中。
使用Spring中的IoC解决程序的耦合:使用配置来实现上面的编码操作。
Spring中基于XML的IOC环境搭建
- Spring依赖包
- 配置 Spring 配置文件 ApplicationContext.xml
- 编写接口及实现类
- 编写测试类
Spring IoC
容器
BeanFactory
是 Spring IoC
容器所定义的最底层接口,而 ApplicationContext
是其高级接口之一
一般使用 ApplicationContext
作为 Spring IoC
容器。
BeanFactory接口
BeanFactory
: 它在构建核心容器时,创建对象的策略是采用延迟加载的方式,什么时候获取 id 对象了,什么时候就创建对象。
- 多例对象适用
getBean
的多个方法:
- 用于获取配置给
Spring IoC
容器的Bean
- 返回值可以是字符串也可以是Class类型
- 返回值是
Class
类型时- 因为
Class
类型可以扩展接口也可以继承父类 - 所以在一定程度上会存在使用父类类型无法准确获得实例的异常
- 因为
isSingleton
用于判断是否单例----该 Bean
在容器中时作为一个唯一单例存在的
isPrototype
用于判断是否多例----当从容器中获取 Bean
,容器就生成了一个新的实例
getAliases
获取别名
ApplicationContext接口
ApplicationContext
:它在创建核心容器时,创建对象采取的策略是采用立即加载的方式,也就是说,只要一读取完配置文件就马上创建配置文件中配置的对象
- 单例对象适用
- 开发中常采用此接口
常用实现类
- ClassPathXmlApplicationContext
- 加载类路径下的配置文件
- 要求配置文件必须在类路径下,否则加载不了 - FileSyetemXmlApplicationContext
- 加载磁盘下任意路径下的配置文件
- 必须有访问权限 - AnnotationConfigApplicationContext
- 用于读取注解创建容器的
Bean的装配与管理
Bean的初始化分为3步:
- Resource 定位:常用XML或者注解
- BeanDefinition 的载入:Spring 根据开发者的配置获取对应的
POJO
,用以生成对应实例的过程 - BeanDefinition 的注册:把
BeanDefinition
载入的POJO
往Spring IoC
容器中注册
创建 bean 对象的方式
-
使用默认构造函数创建
在spring的配置文件中,使用bean
标签,且只使用bean
中的id
和class
属性,没有其他标签
采用默认构造函数
创建bean
对象,此时如果类中没有默认构造函数
,则对象无法创建。<bean id = "创建的对象的id" class = "该对象的类的全限定名"></bean>
-
使用普通工厂中的方法创建对象
使用某个类中的方法创建对象,并存入 Spring容器<bean id = "工厂类的id" class = "工厂类的全限定名"></bean> <bean id = "创建的对象的id" factory-bean="工厂类的id" factory-method="创建对象的方法名"></bean>
-
使用工厂中的静态方法创建对象
使用某个类中的静态方法创建对象,并存入spring容器<bean id = "创建的对象的id" class = "工厂类的id" factory-method="创建对象的静态方法的方法名"></bean>
bean 的作用范围
scope
属性
- 作用:用于指定 bean 的作用范围
- 取值:常用的就是单例和多例
- singletond : 单例的(default)
- prototype : 多例的
- request : 作用于 web 应用的请求范围
- session : 作用于 web 应用的会话范围
- global-session : 作用于集群的会话范围(全局会话范围),当不是集群范围时,它就是 session
生命周期
- 单例对象
- 出生:当容器创建时发生
- 活着:只要容器还在对象就一直活着
- 死亡:容器销毁,对象消亡 - 多例对象
- 出生:当我们使用对象时 Spring 框架为我们创建
- 活着:对象只要是在使用过程中就活着
- 死亡:当对象长时间不用,且没有别的对象引用时,由 Java 的GC回收
总结:单例对象的声明周期和容器相同
依赖注入(Dependency Injection)
概述
依赖注入:组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。容器全权负责的组件的装配,它会把符合依赖关系的对象通过JavaBean属性
或者构造函数
传递给需要的对象。通过JavaBean
属性注射依赖关系的做法称为设值方法注入(Setter Injection
);将依赖关系作为构造函数参数传入的做法称为构造器注入(Constructor Injection
)。
依赖关系的管理:交给Spring来维护。
依赖关系:在当前类需要用到其他类的对象,由Spring为我们提供,我们只需要在配置文件中说明。
依赖关系的维护:依赖注入。
- 能注入的数据:
- 基本类型和 String
- 其他 bean 类型(在配置文件中或者注解中配置过的bean)
- 复杂类型/集合类型
-
IOC的作用:减低程序间的耦合(即依赖关系)
在当前类需要用到其他类的对象,由 Spring 为我们提供,而我们在配置文件中说明依赖关系的维护,这种方式就称为依赖注入。 -
不适合使用依赖注入的情况
1). 经常变化的数据;
注入方式
第一种:使用构造函数提供
使用的标签:`constructor-arg`
标签所在位置:`bean` 标签的内部
标签中的属性:
- type : 用于指定要注入的数据类型,该类型也是构造函数中某个或某些参数的类型
- index : 用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置时从0开始
- name(常用) : 用于指定给构造函数中指定名称的参数赋值
-----------------------------以上三个用于指定给构造函数中的哪个参数赋值---------------------------------
- value: 用于提供基本类型和String类型的数据(写进xml中为string类型,spring能够进行转换成其他基本类型)
- ref : 用于指定其他的bean类型数据。它指的就是在spring的IOC核心容器出现过的bean对象
**特点**:在获取 bean 对象时,注入数据是必须的操作,否则无法操作成功。
**弊端**:改变了 bean 对象的实例化方式,使我们在用不到这些数据的情况下也必须提供带参构造函数,因此开发中较少使用此方法,除非避无可避。
第二种:使用 set 方法提供(更常用的方式)
使用的标签:`property`
标签所在位置:`bean` 标签的内部
标签中的属性:
- name : 用于指定注入时所使用的 set 方法
- value : 用于提供基本类型和 String 类型的数据
- ref : 用于指定其他的bean类型数据,它指的就是在 Spring 容器中出现过的bean对象
**优势**:创建对象时没有明确的限制,可以直接使用默认构造函数。
**弊端**:如果有某个成员必须有值,是有可能 set 方法没有执行。
复杂集合类型的注入方式:
- 用于给 List 结构集合注入的标签
---- list
---- array
---- set
- 用于给map结构集合注入的标签
---- map
---- properties
结构相同,标签可以互换,因此开发中只要记住两组标签即可