作者:周树草 | 来源:互联网 | 2023-02-01 20:39
3.IoC容器3.1SpringIoC容器和bean简介这个章节描述了Spring框架IoC实现原理。IoC也被称为依赖注入(DI).这是一个对象和其他对象一起通过构造函数参数、工程方法参数或
3. IoC容器
3.1 Spring IoC容器和bean简介
这个章节描述了Spring框架IoC实现原理。IoC也被称为依赖注入(DI).这是一个对象和其他对象一起通过构造函数参数、工程方法参数或者对象初始化以后的set方法以及工厂方法的返回值定义它的依赖的过程。在bean创建时,容器将这些依赖注入。由bean自身通过章节构造类或者服务器定位模式等方法去控制实例化或者定位他自己的依赖这过程是反转的,所以被叫做控制反转(IoC)。
org.springframework.beans 和 org.springframework.context 包是Spring IoC容器的基础。BeanFactory接口提供一种管理各种类型对象扩展能力。ApplicationContext是BeanFactory的子接口。它增加了更容易与Spring AOP;消息资源句柄(国际化时使用),事件发布;以及应用层特定的上下文对象,如Web应用程序的WebApplicationContext。总之,BeanFactory提供了配置框架和基础功能,ApplicationContext 增加了更多的企业级特定功能。ApplicationContext 是一个完整的BeanFactory的子类,专门用于IoC容器描述章节中所描述的情况。
使用BeanFactory替代ApplicationContext的更多信息参见章节3.14 The BeanFactory。
在Spring中,那些应用程序的被IoC管理的主要对象被称为beans。一个bean是一个被实例化、装配并被Spring IoC容器管理的对象。另外,bean是应用程序中众多对象的一个。Beans和他们依赖的那些对象都是被容器使用的配置元数据中所引用的。
org.springframework.context.ApplicationContext接口代表Spring IoC容器负责实例化、配置、装配bean。容器通过读取配置元数据实例化、配置以及装配对象。配置元数据通过XML、java注释或者java代码表示。它允许你去描述应用程序中的对象,以及它所依赖的相关对象。
有几个ApplicationContext接口的实现在Spring中支持拆箱即用。在单机环境中ClassPathXmlApplicationContext 或者 FileSystemXmlApplicationContext 是同样的方法。使用传统格式的XML配置元数据时可以指定java注释或者代码作为少量元数据格式描述那些额外的元数据。
对于大多数应用场景,不必明确指定一个Spring IoC容器。例如,Web应用中,web.xml中大约八行的简单J2EE描述就能够完成(参见章节3.13.4 简单实例化web应用的ApplicationContext)。如果你使用Eclipse提供的SpringSource Tool Suite开发环境或者Spring Roo样例配置文件都能在简单的基础点击和键盘后完成。
下面这张图是一个Spring运行的抽象描述。你的应用与配置元数据结合一起,在ApplicationContext被创建和实例化以后,你就会得到一个全面的配置和执行的系统或者应用。
3.2.1 配置元数据
如前所述,Spring IoC容器需要使用某种形式配置元数据。配置元数据用来使开发人员告诉Spring如何去初始化、配置、装配对象。
配置元数据习惯上使用简单直观的XML表示,这用在本章中大部分地方,用来表示Spring的重要概念和特性。
注意:基于XML的配置元数据,不是唯一的配置元数据形式。Spring IoC容器与配置元数据的书写形式进行了完全的解耦。
关于使用其他形式配置元数据进行Spring 容器配置参见
。基于签名的配置:Spring2.5中引进的基于签名的元数据配置。
。基于java的配置:Spring3.0开始,很多特性通过Spring JavaConfig项目引入Spring核心框架。因此,你能够依靠java代码定义beans外观而不是XML文件。这些新特性的用法参考 @Configuration, @Bean, @Import 和 @DependsOn 标签
Spring配置至少由一个,通常是多个bean定义容器所必须的管理。基于XML配置元数据使用元素的子元素完成。
这些bean定义符合实际的对象构成你的应用。典型的,你定义服务层对象,数据访问对象(DAO),描述对象如Struts Action实例,底层对象如Hibernate SessionFactory,JMS队列等等。同样不会在容器中配置细粒度的领域对象,因为他们经常被用在DAO与业务逻辑是被创建和加载。然而,你能使用Spring整合的AspectJ在IoC容器控制器外部配置这些对象的创建。参见《在Spring中使用AspectJ依赖注入领域对象》
下面范例显示了使用XML进行元数据配置的基本结构:
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">
这里的id属性是一个唯一标识bean的字符串。class属性定义bean的类型,需要使用全路径类名。id属性的值指定了一个被管理的对象。XML引用的那些对象没有在这个例子中显示,参照《3.4 依赖》章节中的信息。
3.2.2 实例化容器
实例化容器是非常简单的。将资源文件的路径传递给ApplicationContext 的构造函数去指定实际的资源,容器从资源文件中读取元数据配置,这些资源字符串可以来自本地文件系统,java类路径等多种方式。如下:
ApplicationContext cOntext=
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
注意:你学习了Spring IoC容器以后,你应该知道更多关于Spring资源抽象的知识,这些在《第四章 资源》中有描述,描述了一种简单的通过URI描述符定位InputStream进行读取,特别是,在章节4.7中“应用程序上下文和资源路径”中使用资源路径构造应用成熟上下文的描述
下面范例展示了一个服务层对象的配置:
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">
class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
下面范例展示了数据访问对象的配置:
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">
class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapAccountDao">
上面的例子中,服务层由PetStoreServiceImpl对象组成,SqlMapAccountDao 和iBatis的SqlMapItemDao 对象组成了数据访问对象。“名称”元素引用java bean的成员名称,ref 元素引用其他定义的bean的名称。将id和ref连起来表示合作对象之间的依赖关系。详细的对象依赖配置见《3.4 依赖》章节
3.2.2.1构成基于XML的配置元数据
它能够跨对个XML文件对bean进行定义。通常每个独立的XML配置文件代表架构上一个逻辑层或者模块。
你能够通过应用程序上下午构造函数读取所有这些XML片段中的bean定义。就像上节中描述的,构造函数带有多种的资源定位。作为一种选择,你可以定义一个或者多个去从文件中读取bean定义,如下:
在之前的例子中,扩展bean定义从services.xml, messageSource.xml和 themeSource.xml 三个文件中读取。所有路径位置是相对于定义文件而作的,所以,services.xml一定是与导入文件在同一个目录或者类路径下的,messageSource.xml 和 themeSource.xml 一定是相对resources的下级位置导入的。就像看到的,考虑到这些路径是相对的,斜线被忽略了,最好是永远不要用斜线。被导入的文件内容,包含顶层的元素必须是符合XML的Spring Schema或者DTD的。
注意:在引用路径时,直接使用上级路径的“../”表示是可以的,但是不推荐这么使用。这样会使用当前应用外部的文件创建依赖。尤其,不推荐使用“classpath:” URL定位(例如“classpath:../services.xml"),这在运行时,进程会查找最近的classpath的根目录的上级目录。Classpath的改变可能会找到不同的,错误的目录。
你应该全部使用全路径的资源定位代替相对路径的定位,例如:"file:C:/config/services.xml" 或者 "classpath:/config/services.xml".然而,你一定意识到了你的配置信息与应用程序的绝对路径耦合在一起了。通常,对于这样的绝对路径要保持一个间接的路径使用,例如,通过"${...}" 占位符解耦运行时JVM系统参数。
3.2.3 使用容器
ApplicationContext 是能够管理bean以及它所依赖的对象的先进工厂的接口。使用方法 T getBean(Stringname, Class requiredType)能够找到需要的bean的实例。
ApplicationContext 能够读取bean定义并访问,如下:
// create and configure beans
ApplicationContext cOntext=
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
// retrieve configured instance
PetStoreServiceImpl service = context.getBean("petStore", PetStoreServiceImpl.class);
// use configured instance
List userList service.getUsernameList();
使用getBean()查找bean的实例。ApplicationContext 接口还提供了很少的另外几个方法用于查找bean,但对于应用来说,可能你从不会去使用它们。事实上,你的代码应该从来没有调用过getBean()方法,它们也不依赖Spring的API。例如,Spring与web框架提供如控制器和JSF-managed bean的各种依赖注入的web框架类。