IOC是什么
IoC 有时也被称为依赖注入 (DI)。这是一个对象定义他们依赖的过程,其中对象之间的相关性,也就是说,它们一起工作,只能通过构造函数参数,参数工厂方法或设置在其构造后的对象实例或者是从一个工厂方法返回的对象实例的属性上。
在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制(也就是new对象)。理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”。
org.springframework.beans 和 org.springframework.context 是Sprig 框架的 IoC 容器的基础包的。 BeanFactory 提供能够管理任何类型的对象的高级配置机制。 ApplicationContext 是 BeanFactory 的一个子接口。它增加了与 Spring AOP 功能的整合更容易;消息资源处理(用于国际化),事件发布;和应用层的上下文,如WebApplicationContext 中的 Web 应用程序使用。
简而言之,BeanFactory 提供了配置框架和基本功能,而ApplicationContext 则增加了更多支持企业特定的功能。一个ApplicationContext 是 BeanFactory 的一个完整的超集。
在 Spring 中,形成了应用程序的骨架,该对象由 Spring IoC 容器管理被称为 bean。一个 bean 是由 Spring IoC 容器实例化,组装,并以其他方式管理的对象。否则,一个 bean 只是简单的应用程序中的许多对象之一。bean,以及它们之间的相关性,反映在所使用的容器的配置元数据中(configuration metadata )。
IoC容器的概念
IoC容器就是具有依赖注入功能的容器,IoC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需直接在代码中new相关的对象,应用程序由IoC容器进行组装。
Bean的概念
由IoC容器管理的那些组成你应用程序的对象我们就叫它Bean,Bean就是由spring容器初始化、装配及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别。
容器总览
org.springframework.context.ApplicationContext 代表 Spring IoC 容器,并负责实例化,配置和组装上述 bean 的接口。容器是通过对象实例化,配置,和读取配置元数据汇编得到对象的构建。配置元数据可以是用 XML,Java 注解,或 Java 代码来展示。它可以让你描述组成应用程序的对象和对象间丰富的相互依赖。
Spring ApplicationContext 接口提供了几种即装即用的实现方式。在独立应用中,通常以创建ClassPathXmlApplicationContext 或FileSystemXmlApplicationContext 的实例。虽然 XML 一直是传统的格式来定义配置元数据,但也可以指示容器使用 Java 注解或代码作为元数据格式,并通过提供少量的XML配置以声明方式启用这些额外的元数据格式的支持。
下面的图展示了 Spring 是如何工作的
配置元数据
如上述图所示,Spring IoC 容器使用 配置元数据( configuration metadata);这个配置元数据代表了应用程序开发人员告诉Spring 容器在应用程序中如何来实例化,配置和组装对象。
基于 XML 的元数据并不是配置元数据的唯一允许的形式。
1. 基于注解的配置:Spring 2.5 的推出了基于注解的配置元数据支持。
2. 基于Java的配置:Spring3.0 开始,由 Spring JavaConfig 项目提供了很多功能成为核心 Spring 框架的一部分。因此,你可以通过使用Java,而不是 XML 文件中定义外部 bean 到你的应用程序类。要使用这些新功能,请参阅
@Configuration,@Bean,@Import 和 @DependsOn 注解。
基于 XML 的配置元数据显示这些 bean 配置的 包含于
顶层元素 元素。
Java 配置通常使用 @Configuration 类中 @Bean 注解的方法。
以下示例显示基于 XML 的配置元数据的基本结构:
<?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.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 的类型,并使用完整的类名。 id 属性的值是指协作对象。
实例化容器
实例化 Spring IoC 容器是直截了当的。提供给 ApplicationContext构造器的路径就是实际的资源字符串,使容器装入从各种外部资源的配置元数据,如本地文件系统, Java CLASSPATH,等等。
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
下面的例子显示了服务层对象(services.xml中)配置文件:
<?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.xsd">
<!-- services -->
<bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
<property name="accountDao" ref="accountDao"/>
<property name="itemDao" ref="itemDao"/>
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions for services go here -->
</beans>
下面的例子显示了数据访问对象 daos.xml 文件:
<?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.xsd">
<bean id="accountDao"
class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
<!-- additional collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions for data access objects go here -->
</beans>
撰写基于XML的配置元数据
它可以让 bean 定义跨越多个 XML 文件,这样做非常有用。通常,每个单独的 XML 配置文件代表你的架构一个逻辑层或模块。
您可以使用应用程序上下文构造从所有这些 XML 片段加载 bean 定义。这个构造函数的多个 Resource 位置,作为上一节中被证明。另外,使用 元素的一个或多个出现,从另一个或多个文件加载 bean 定义。 例如:
<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 在前面的例子中,外部 bean 定义是由三个文件加载而来。所有位置路径是相对于导入文件的,因此 services.xml 是必须和导入文件在同一目录或类路径中的位置,而 messageSource.xml和 themeSource.xml 来必须在导入文件的 resources 以下位置。正如你所看到的,前面的斜线被忽略,但考虑到这些路径是相对的,它更好的形式是不使用斜线。该文件的内容被导入,包括顶级 元素,必须根据 Spring Schema 是有效的XML bean 定义
使用相对“../”路径引用父目录中的文件是可能的,但不推荐使用。这样做会创建对当前应用程序之外的文件的依赖。特别地,不推荐在“classpath:”URL(例如“classpath:../ services.xml”)中引用此引用,其中运行时解析过程选择“最近”类路径根,然后查看其父目录。Classpath配置更改可能导致选择不同的目录不正确。
您可以随时使用完全限定的资源位置而不是相对路径:例如“file:C:/config/services.xml”或“classpath:/config/services.xml”。但是,请注意,您将应用程序的配置与特定的绝对位置相结合。通常优选的是保持这种绝对位置的间接,例如通过在运行时解决JVM系统属性的“$ {…}”占位符。
使用容器
该ApplicationContext是一个维护bean定义以及相互依赖的注册表的高级工厂的接口。使用方法T getBean(String name, Class requiredType)就可以取得bean的实例。
在ApplicationContext可以读取bean定义并访问它们,如下所示:
ApplicationContext context =
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
PetStoreService service = context.getBean("petStore", PetStoreService.class);
List<String> userList = service.getUsernameList();