介绍IoC容器
IoC容器也被称为依赖注入(DI,dependency injection)。这就是一个过程,在这个过程中,对象通过构造器参数、工厂方法参数或者是工厂方法返回后的对象上的属性来定义依赖项。IoC容器会在创建这些bean的时候注入这些依赖,这个过程完全是交由容器处理(正如其名:控制反转)。
org.springframework.beans
和 org.springframework.context
包下的类是IoC 容器的基础。 BeanFactory
提供了管理任何类型对象的高级配置机制。 ApplicationContext
是 BeanFactory
的子接口,它添加了以下功能:
- 集成Spring AOP特性
- 国际化(i18n)
- 事件发布(ApllicationEvent)
- 应用级容器,例如:
WebApplicationContext
构建web应用
总而言之,BeanFactory
提供了配置框架和基本功能,ApllicationContext
则提供了更多企业级的功能。ApllicationContext
完全是扩展自BeanFactory
(子集关系)。
在spring中,被springIoC容器所管理的、组成应用的对象就叫Spring Bean,一个Bean会被Spring IoC容器所实例化、收集和管理。除此之外,bean只是我们应用容器中许多对象的其中之一。Bean之间的依赖关系通过容器中的配置元数据(BeanDefinition)进行展示。
容器概览
org.springframework.context.ApplicationContext
接口呈现了IoC容器并且负责实例化、配置、收集Bean。容器会通过读取配置元数据来进行实例化、配置和收集Bean。配置元数据可以通过XML、Java注解、Java代码来定义。通过定义可以让我们表示组成应用的对象信息以及对象之间的内部依赖关系。
Sprin提供了ApllicationContext
的许多实现类,在标准的独立应用中,创建 ClassPathXmlApplicationContext
或者 FileSystemXmlApplicationContext
是常见的选择。尽管XML是定义配置元数据的传统格式,但是我们可以通过提供少量XML配置来声明式地启用对这些其他配置元数据格式的支持,从而指示容器将Java注释或代码用作元数据格式。
在大多数应用场景下,不需要用户显式的创建一个或多个Spring IoC容器。
下图展示了spring是如何工作的,我们的应用Java类和配置元数据被整合在一起,在创建完ApllicationContext
后,将会得到一个完全可配置并且可执行的系统或应用程序。
配置元数据
像上图所展示的,Spring IoC容器会使用一系列配置元数据,配置元数据能让开发者定义Spring容器如何实例化、配置、收集应用程序中的对象。
配置元数据支持以XML格式定义,但是当今许多开发者选择使用基于Java的配置方式。
使用其他形式配置:
- 基于注解配置: Spring 2.5 支持基于注解配置
- 基于Java配置: Spring 3.0开始,SpringJava配置项目提供的新特性被加入到Spring的核心框架中。这样就不仅可以使用XML配置还能使用新特性:
@Configuration
,@Bean
,@Import
,@DependsOn
注解
Spring配置必须又至少管理了一个Bean定义的容器组成。XML通常使用@Bean
注解被@configuration
类的方法上来定义
这些bean定义对应的真实对象组成了应用程序,通常来说,我们定义的服务层、DAO、表述层对象,应用基础对象。通常,不会在容器中配置细粒度的域对象,因为DAO和业务逻辑通常负责创建和加载域对象。如果要配置IoC容器之外的对象可以使用Spring Aspectj整合
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
id
是Bean定义的唯一标识class
定义了bean的类型,使用全类名
实例化一个IoC容器
ApplicationContext
可以从多种外部资源进行加载,比如:本地文件系统,Java类路径等等。
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
}
组合XML配置
分多个XML文件配置Bean definition是十分有用的,每个XML都可以独立呈现应用程序的逻辑或者模块
可以使用application context的接受多个Resource
参数的方法来加载多个XML定义,也可以使用
<beans>
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resources/themeSource.xml"/>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
</beans>
以上配置加载了三个文件:services.xml
, messageSource.xml
, themeSource.xml
。services.xml
地址都是相对路径,所以services.xml
文件必须在同一个目录下活类路径下,而 messageSource.xml
和 themeSource.xml
必须在resources
目录下。能发下的是:地址开头的“/”已经被忽略了,所以鉴于这些路径是相对路径,最好不要使用斜线开头。
TIPS:虽然能使用“../”来获取上级目录但是并不是被推荐的方式,这样做会依赖应用外部的文件,更不建议在类路径中使用:比如
classpath:../services.xml
,如果类路径配置改变将会导致不同的,不正确的目录。也可以使用绝对路径而不是相对路径file:C:/config/services.xml
或者classpath:/config/services.xml
但是要注意到应用程序已经耦合了文件系统绝对路径,通常使用绝对路径更好的做法是使用占位符,通过在运行时针对JVM系统属性解析的“ $ {…}”占位符。
使用容器
ApplicationContext
是一个管理不同bean注册以及它们的依赖的高级工厂接口类,通过使用T getBean(String name, Class<T> requiredType)
可以得到想要的实例。
ApplicationContext
能够让开发者读取bean定义的信息,并访问它们:
// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);
// use configured instance
List<String> userList = service.getUsernameList();
我们可以使用getBean
来获取bean,ApplicationContext
还有许多获取bean的方法,但是我们的业务代码最好不要使用它们,这样就不会依赖spring的api。