控制反转:
意思是程序中的应用程序对象之间的关系,不用代码控制,而完全是由容器来控制。在运行阶段,容器会根据配置信息直接把他们的关系注入到组件中。同样,这也是依赖注入的含义。依赖注入和控制反转其实是一个概念。只不过强调的不同而已,依赖注入强调关系的注入是由容器在运行时完成,而控制反转强调关系是由容器控制。其实本质是一样的。
Web 应用程序由大量的应用程序组件组成,这些组件共同协作来执行应用程序的业务逻辑。称为应用程序对象的这些应用程序组件必须知道它们要与之协作的所有其他对象。Web 应用程序可以使用传统的J2EE 方法来创建。这种应用程序由一个或多个类组成,它们互相协作以实现所需的业务逻辑。
然而,每个类对象获取它自己对与它协作的对象的引用(依赖)。
这导致了紧耦合代码,这样的代码难以进行单元测试。
例如:
public class Order{
.....
private Product prod;
private Customer cust;
public Order(){
//Order class is creating its dependent objects
cust = new Customer();
prod = new Product();
}
......
}//通过new运算符在Order类中创建了Product和Customer类的新实例。
Spring容器
在支持Spring 的应用程序中,Spring 容器在运行时提供所有对象及其必需的依赖。
由Spring 容器将依赖自动注入Order类,如下图所示:
所有应用程序对象都驻留在Spring 容器内。此外,Spring
容器还使应用程序对象能互相协作,以实现必要的应用程序需求。
下图显示了包含各种应用程序对象的Spring 容器:
Spring 容器基于DI 的概念来管理应用程序对象。您无需创建对象;只是必须描述将如何创建对象。容器将在需要时自动创建它们。容器还将创建协作对象之间的关联。这些对象容易编码,容易进行单元测试,并支持重用。
Spring 框架提供了以下容器类型:
- bean 工厂:
是简单的容器,提供对DI 的支持。
是由org.springframework.beans.factory.BeanFactory接口定义的。
- 应用程序上下文:
基于bean 工厂容器的概念构建。
提供其他功能,如:容易与Spring AOP 功能集成,并支持国际化。
是由org.springframework.context.ApplicationContext接口定义的。
bean工厂
在Spring 中,bean 可以是Spring 容器创建和管理的任何Java 对象或类实例。
bean 工厂容器用于:
实例化、配置和管理Web 应用程序的对象(bean)。
在实例化各种对象时定义它们之间的关系。
bean 工厂创建的对象:
是完全配置的。
可供使用。
知道它们与其他应用程序对象之间的关系。
bean 工厂由org.springframework.beans.factory.BeanFactory
接口表示。
Spring 框架提供bean 工厂的几种实现,它们支持应用程序中各种级别的功能。
最常用的bean 工厂是由org.springframework.beans.factory.xml.XmlBeanFactory接口表示的XML bean 工厂。
XML bean工厂
XML bean 工厂基于XML 文件中提供的bean 定义来加载bean。
此XML 文件也称为bean 配置文件。
配置文件是设置任何支持Spring 的应用程序的关键。
以下代码段表示bean 配置文件的语法:
<?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-3.0.xsd">
...
</beans>
在bean 配置文件中,使用<beans>
标记中的<bean>
标记定义每个bean。
bean 定义包含容器必须知道的关于bean 的基本信息,如:
创建bean 的过程。
关于bean 生命周期的详细信息。
该bean 的各种依赖。
<bean>
标记包含以下属性来定义bean:
id用于唯一标识Spring 容器中的bean。它定义默认的bean 名称。
name 用于指定bean 的别名。
class 用于指定bean 类的全限定名称(包名称+ 类名称)。
scope 用于定义被定义的bean 的作用域,它可以有singleton或prototype这两个值中的任何一个。
例如:
<?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-3.0.xsd">
<bean id="Beckham" class="Sport.LAGalaxy"/>
<!--表示Sport包中的LAGalaxy类被声明为ID 是Beckham的bean-->
</beans>
加载bean配置文件
要实例化Web 应用程序中的bean 工厂,需要加载bean 配置文件。这可以使用org.springframework.core.io.Resource接口定义的Resource对象来完成。
Resource对象为bean 工厂提供bean 配置文件来通过从配
置文件中读取bean 定义来加载bean。
您可以从不同位置加载bean 配置文件,如:
文件系统
类路径
外部URL
Spring 框架提供了Resource接口的几种实现,如下表所示:
例如:
Resource res = new ClassPathResource(“Sport/Spring-Config.xml”);
创建XML bean工厂的实例
将配置文件加载到Resource对象中后,需要创建XML bean 工厂的实例,如以下代码段所示:
BeanFactory factory = new XmlBeanFactory(res);
bean 工厂还通过定义bean 的作用域帮助您控制要创建的某个bean 的实例个数,是整个应用程序一个实例还是每个请求一个实例。
bean 工厂支持以下类型的bean 作用域:
单例:提供具有特定名称的bean 的共享实例,并将它放在工厂中。
原型:提供bean 的单个实例,并保证用户请求将导致仅为单个用户创建独立的bean。
检索bean的实例
将bean 加载到容器中时,bean 工厂并不实例化bean。
bean 工厂立即加载所有bean 定义,但在用户实际需要bean 之前不会实例化bean。
您可以使用getBean()方法从bean 工厂检索用给定的名称注册的bean 的实例。
此方法将bean 的ID 作为字符串值。
例如:
LAGalaxy team = (LAGalaxy)factory.getBean(“Beckham”);
team.squadSize();
<!--getBean()方法加载ID为Beckham 的bean。此bean 属于LAGalaxy类型。-->
调用getBean()方法时,bean 工厂容器实例化bean 并通过DI 设置其属性。
现在,bean 的生命在Spring 容器中开始。
bean工厂中bean的生命周期:
在bean 工厂中bean 的生命周期期间执行了以下步骤:
实例化
填充属性
设置bean 名称
设置bean 工厂
预初始化
初始化bean
初始化后
bean 可供使用
销毁bean
应用程序上下文
您可以使用bean 工厂容器创建简单的支持Spring 的应用程序。
应用程序上下文是高级容器,它提供了几种企业级别功能,例如:
- 提供解析文本消息的方式,包括支持这些消息的国际化。
- 提供加载图像之类文件资源的常规方式。
- 将事件发布到作为侦听器注册的bean。
此外,它还继承了BeanFactory接口的所有功能,如:创建bean。将它们互相关联。根据请求将它们发给用户。
bean 工厂用于缺乏特定资源(如:内存空间)的情况。
Spring 框架提供了应用程序上下文容器的以下常用实现:
ClassPathXmlApplicationContext
用于加载位于指定类路径的bean 配置文件。
FileSystemXmlApplicationContext
用于加载指定的文件系统中提供的bean 配置文件。
XmlWebApplicationContext
用于从web.xml 文件中的contextConfigLocation上下文参数指定的位置加载bean 配置文件。
加载应用程序上下文:
要使用应用程序上下文容器来管理应用程序对象,必须加载某个ApplicationContext实现。
例如:
ApplicationContext appContext = new ClassPathXmlApplicationContext(“Sport/Spring-Config.xml”);
<!--从指定的类路径Sport/Spring-Config.xml加载bean 配置文件。-->
要在应用程序中实现FileSystemXmlApplicationContext,可以使用以下代码段:
ApplicationContext appContext = new FileSystemXmlApplicationContext(“c:/Sport/Spring-Config.xml”);
<!--从指定的文件路径c:/Sport/Spring-Config.xml加载bean 配置-->
如果您要在应用程序中实现XmlWebApplicationContext,可以使用以下代码段:
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
<!--加载Web 应用程序的WEB-INF 文件夹中存储的applicationContext.xml 文件。-->
应用程序上下文容器和bean 工厂容器之间的主要区别:
bean 工厂容器以缓慢的方式加载所有bean,这意味着只在您调用getBean()方法时才创建bean。
应用程序上下文容器不会等待getBean()方法被调用;一旦应用程序上下文启动,它就会预加载所有bean。
预加载bean 确保了当应用程序需要它们时它们可用。
应用程序上下文中bean 的生命周期:
应用程序上下文容器包含一个额外的步骤:设置应用程序上下文。
此步骤紧跟在bean 工厂容器中bean 生命周期的步骤4(bean 工厂设置)后执行。
在此步骤中,需要通知bean 它所驻留的应用程序上下文容器。