ioc 容器


介绍IoC容器

​ IoC容器也被称为依赖注入(DI,dependency injection)。这就是一个过程,在这个过程中,对象通过构造器参数、工厂方法参数或者是工厂方法返回后的对象上的属性来定义依赖项。IoC容器会在创建这些bean的时候注入这些依赖,这个过程完全是交由容器处理(正如其名:控制反转)。

org.springframework.beansorg.springframework.context 包下的类是IoC 容器的基础。 BeanFactory 提供了管理任何类型对象的高级配置机制。 ApplicationContextBeanFactory的子接口,它添加了以下功能:

  • 集成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后,将会得到一个完全可配置并且可执行的系统或应用程序。

container magic

配置元数据

像上图所展示的,Spring IoC容器会使用一系列配置元数据,配置元数据能让开发者定义Spring容器如何实例化、配置、收集应用程序中的对象。

配置元数据支持以XML格式定义,但是当今许多开发者选择使用基于Java的配置方式。

使用其他形式配置:

Spring配置必须又至少管理了一个Bean定义的容器组成。XML通常使用标签定义,而Java配置则通常使用@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>
  1. id是Bean定义的唯一标识
  2. 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定义,也可以使用标签来加载其他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.xmlservices.xml地址都是相对路径,所以services.xml文件必须在同一个目录下活类路径下,而 messageSource.xmlthemeSource.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。


文章作者: Ubi-potato
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Ubi-potato !
评论
  目录