Spring的容器机制
容器是Spring框架实现功能的基础,Spring容器类似一家超级工厂,当Spring启动时,所有被配置过的类都会被纳入Spring容器的管理之中。
Spring把它管理的类称为Bean,Spring可以通过XML文件或注解获取配置信息,进而通过容器对象来管理Bean。Spring对Bean的管理体现在它负责创建Bean并管理Bean的生命周期。Bean运行在Spring容器中,它只需发挥自己功能,而无须过多关注Spring容器的情况。
BeanFactory接口
BeanFactory接口是Spring中IOC(控制反转)最基本的容器接口,它定义了创建和管理Bean的方法。
ApplicationContext接口
- ApplicationContext接口的功能建立在BeanFactory接口的基础之上,它增强了BeanFactory的特性,增加了更多企业级的功能。
- ApplicationContext接口为应用提供国际化访问功能,提供资源的访问支持,可同时加载多个配置文件,引入事件机制,让容器在上下文中提供了对应用事件的支持,以声明式方式启动并创建Spring容器。除此之外,ApplicationContext接口可以为单例的Bean实行预初始化,并根据元素执行setter方法,这决定了此时单例的Bean可以被直接使用,提升了程序获取Bean实例时的性能。
类名称 | 描述 |
---|---|
ClassPathXmlApplicationContext | 从类路径加载配置文件,创建ApplicationContext实例 |
FileSystemXmlApplicationContext | 从文件系统加载配置文件,创建ApplicationContext实例 |
AnnotationConfigApplicationContext | 从注解中加载配置文件,创建ApplicationContext实例 |
WebApplicationContext | 在Web应用中使用,从相对于Web根目录的路径中加载配置文件,创建ApplicationContext实例 |
ConfigurableWebApplicationContext | 扩展了WebApplicationContext,它允许通过配置的方式实例化WebApplicationContext |
容器的启动过程
Spring容器的启动过程包括三个基本步骤:BeanDifinition的Resource定位、BeanDifinition的载入与解析、BeanDifinition在Spring容器中的注册。
- 在获取配置信息时,Spring容器首先需要找到具体的Resource,Resource可以是XML文件,也可以是注解;
- 读取配置信息,将配置信息转换为Spring容器内部的数据结构,这个数据结构就是BeanDifinition,通过BeanDifinition,Spring能够方便地对Bean进行管理;
- 在完成BeanDifinition载入后,需要将BeanDifinition注册到Spring容器内部的数据结构,这个数据结构就是BeanDifinition。通过BeanDifinition,Spring能够方便地对Bean进行管理。
使用Spring管理Bean
容器功能是Spring的基础功能,当Bean被配置到Spring之后,对象的生命周期及依赖关系就会纳入Spring的统一管理。在实际开发中,基于容器功能,Spring可有效降低类与类之间的耦合,同时对类的统一管理也可以简化开发,提升开发效率。
IOC和DI
IOC是Inversion Of Control(控制反转),它是一种设计思想,是指将对象的控制权由程序代码反转给外部容器。在Spring中,控制反转是实现Spring容器的指导思想。有了Spring容器,开发人员无须编写管理对象生命周期和依赖关系的代码,此项工作将由Spring容器根据配置自动完成。
DI(Dependency Injection)依赖注入,它是控制反转的另一种说法,同时也为控制反转提供了实现方法。依赖注入是指调用类对其他类的依赖关系由容器注入,这就避免了调用类对其他类的过度依赖,降低了类与类之间的耦合。
依赖注入的方式
依赖注入有三种方式:
- 构造器注入
- 属性注入
- 接口注入
构造器注入指的是在被注入的类中声明一个构造方法,而构造方法可以是有参或无参的。Spring在读取配置信息后,会通过反射方式调用构造方法,如果是有参构造方法,可以在构造方法中传入所需的参数值,进而创建类对象。
属性注入
属性注入是Spring中最主流的注入方法,这种注入方法简单、直观,它是在被注入的类中声明一个Set方法,并通过该Set方法的参数注入对应的值。
Bean的配置
元素的属性
属性 | 描述 |
---|---|
Class | 指定Bean对应类的全路径 |
Name | 指定Bean对应对象的一个标识 |
Scope | 指定Bean对象的作用域 |
id | id是Bean对象的唯一标识,Spring通常通过id属性完成对Bean的配置、管理 |
lazy-init | 是否延时加载,默认值为false |
init-method | 对象初始化方法 |
destroy | 对象销毁方法 |
注入集合:
list、map…
在Spring容器中,一个Bean的属性值可能是另外一个Bean的实例,即当前Bean对其他Bean存在依赖关系,此时需要将其他Bean的实例配置为当前Bean的属性,这可以通过元素或元素的ref属性来实现:
使用P:命名空间注入
Spring的配置文件一般基于元素来配置Bean的属性,但是当Bean实例的属性足够多时,使用大量的元素配置属性就显得冗余,所以Spring引入了P:命名空间。
P:命名空间也是通过属性注入实现的,和使用元素不同的是,当导入P:命名空间以后,可以通过P:属性完成属性注入,而不再依靠元素。
若想使用P:命名空间,则需要在applicationContext.xml文件的开头加上一句:
xmlns:p="http://www.springframework.org/schema/p"
使用:
<bean id="teacher" class="com.neu.bean.Teacher p:tid=
"1" p:name="Lisa" p:stu-ref="student"></bean>
使用SpEL注入
SpEL是Spring Expression Language(Spring表达式语言),它是一种支持查询和操作运行时对象导航图功能的表达式语言,可以简化开发,能够减少代码逻辑和配置信息的编写;
SpEL的语法与EL类似,它以#{…}为定界符,能够为Bean的属性进行动态赋值,它可以通过Bean的id引用Bean,调用对象的方法或引用对象的属性、计算表达式的值,匹配正则表达式等。
Bean的作用域
在Spring容器中,Bean的作用域是指Bean实例相对于其他Bean实例的请求可见范围:
属性 | 描述 |
---|---|
Singleton | 单例模式,作用域为singleton的Bean在Spring容器中只会存在一个共享的Bean实例,所有对Bean的请求只要id与Bean的定义相匹配,则只会返回Bean的同一实例 |
Prototype | 每次从容器中调用Bean时,都会产生一个新的Bean实例 |
Request | 一个HTTP请求会产生一个Bean对象,也就是说吗,每一个HTTP请求都有自己的Bean实例,只在基于Web的Spring ApplicationContext中可用 |
Session | 限定一个Bean的作用域为HTTPsession的生命周期,只有基于Web的Spring ApplicationContext才能使用 |
global session | 限定一个Bean的作用域为全局HTTPsession的生命周期,只有在Web应用中使用Spring时,该作用域才有效 |
Bean的生命周期
Bean的生命周期是指Bean实例被创建、初始化和销毁的过程。在Bean的生命周期中,有两个时间节点非常重要,这两个时间节点分别是Bean实例化以后和Bean实例销毁之前,实际开发中,有时需要在这两个时间节点完成一些指定操作,例如,在Bean实例初始化之后申请某些资源、在Bean实例销毁之前回收某些资源等。
1.init-method destroy-method
2.implements InitializingBean implements DisposableBean
注解
除了XML文件,Spring还支持通过注解实现Bean的管理。注解直接写在代码中,使用注解可以减少XML文件的配置内容,并且注解能够实现自动装配,提供的功能也更为强大。使用注解可以实现和采用XML文件形式相同的效果。
这里不再赘述,具体情况使用时可查看Spring的API…