spring文档阅读——Core: The IoC Container
用了这么久的spring框架却一直不知其所以然,直接在网上看别人的攻略又感觉差了点什么,因此决定系统的看一下spring官方的英文文档。本系列博客将按照每一篇文章对应官方文档中的一个小节的形式发布,文章内容分为正文和单词两部分。
笔者的英文水平一般,正文中的引用翻译也只是部分翻译,故本文只是spring文档阅读过程中的记录和分享,不可作为译文参考。
官方文档地址:https://spring.io/projects/spring-framework
欢迎转载,转载时注明原作者即可。
正文
本文所列部分对于spring框架而言都是核心技术,缺一不可。
Spring IoC容器
1. IoC和Bean简介
Foremost amongst these is the Spring Framework’s Inversion of Control (IoC) container.
IoC is also known as dependency injection (DI).
如果要在spring框架所有核心技术中挑出一个最重要的,那一定是IoC(控制反转)
/DI(依赖注入)
(是的,它们其实是同一个东西)。以下是关于IoC
的定义:
It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean.
IoC指的是对象仅通过构造函数的参数
、工厂方法的参数
、或者是被构造函数或工厂方法创建后返回的属性
来定义自身依赖的过程。当容器创建bean时就会将那些已经被定义过的依赖注入进去。
IoC的两个关键包分别是org.springframework.beans
和org.springframework.context
。
BeanFactory
是提供框架配置和基本功能的接口,它的配置机制使得我们可以轻易的管理任何类型的对象。BeanFactory
的子接口ApplicationContext
则补充了一些企业开发相关的功能,ApplicationContext
同时也是BeanFactory
的超集。
在spring中,被IoC容器实例化、组装或以其他方式管理的对象称为bean
。各种bean
以及它们之间的依赖关系反映在spring容器配置的元数据
中。
此处文档中还有一句
Otherwise, a bean is simply one of many objects in your application.
,我的理解是此处的bean
指的是javabean
,希望有大佬解惑
2. 容器概览
org.springframework.context.ApplicationContext
接口代表着spring IoC容器,它负责通过读取元数据
获取有关对象的配置说明并实例化、配置和组装bean
。配置元数据
通常以xml
、注解
或java代码
的形式表示,元数据
中包含了组成应用程序的对象以及这些对象之间复杂的依赖关系。spring已经预设了一些ApplicationContext
接口的实现,如ClassPathXmlApplicationContext
和FileSystemXmlApplicationContext
等。下图展示了spring的工作原理视图:
2.1 配置元数据
开发者可以通过配置元数据
告诉spring容器如何实例化、配置和组装对象,传统情况下(spring2.5以前)以xml
格式表示(如果用springboot
的话一般不需要写配置文件,而是通过在标注了@Configuration
的类里添加带@Bean
的方法),spring配置由容器必须管理的至少一个或多个bean
定义组成。
Java configuration typically uses @Bean-annotated methods within a @Configuration class.
- 从spring2.5开始,spring框架开始支持注解配置模式
- 从spring3.0开始,spring框架开始支持代码配置模式
以下是一个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">
<!-- 引入其他的xml文件 -->
<import resource="xxx.xml"/>
<import resource="resources/yyy.xml"/>
<import resource="/resources/zzz.xml"/>
<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>
2.2 实例化容器
ApplicationContext
的构造函数可以从参数(一个或多个字符串)中获取到外部资源路径,然后再从这些外部资源中读取配置元数据
,以下是通过ClassPathXmlApplicationContext
构造ApplicationContext
的例子:
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
除了xml
外,也可以通过dsl(Groovy)
定义bean。但是由于我没有在项目中实际使用过,所以在此不作举例。
2.3 容器的使用
ApplicationContext
是一个高级接口,它维护着不同的beans及其依赖
的注册表。通过方法
T getBean(String name, Class<T> requiredType)
可以获取到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
实例,spring还提供了一些其他的方法达到相同的目的,但是我们基本上用不到这些方法。而且按照官方的说法,我们甚至连getBean()
都不需要调用,业务逻辑不需要依赖spring的API。以web为例,推荐的做法是通过注解(@Service
、@Controller
等)声明bean
。
3. Bean概览
spring IoC
容器管理着许多通过配置元数据
创建的bean
。
对于容器本身而言,bean定义
被表示为BeanDefinition
对象,它包含了以下元数据:
- 包限定类名,指向bean的实际实现类;
- bean在容器中的行为,包括作用域、生命周期回调等;
- 使bean正常工作所需的其他bean的引用,即依赖;
- 其他配置,如连接池的连接数限制或大小限制等。
以下是一个bean定义
的例子:
<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>
3.1 Bean的命名规范
在spring容器中,每个bean至少有一个标识符,且每个标识符必须具有唯一性。一般情况下一个bean只会有一个标识符(使用id
属性),如果需要多个标识符的话,额外的标识符被称为alias(别名)
。
在xml格式的配置元数据中, 可以使用id
属性、name
属性或两者来指定 bean 标识符,两者都允许使用字母、数字、某些特殊字符来精确描述bean的特征。
id
和name
不是必填项,如果没有为bean指定id
和name
,容器会自动为bean生成一个唯一的name
。但是如果使用者需要通过ref元素
按name
查找bean,则必须手动指定bean的name
属性。
bean的命名遵循驼峰命名法
:首字母小写,其后每一个单词的首字母大写。比如:password、userAccount、fatSuperMan等。bean的名称最好与其作用相关,方便阅读和理解。
关于aliases
:
在大型系统中,相同的bean在每个子系统都有不同的对象定义,这时我们可以使用alias
来为bean定义别名:
<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>
在上面的例子中,对于同一个beanmyApp-dataSource
,子系统A通过subsystemA-dataSource
引用,子系统B通过subsystemB-dataSource
引用。以上配置使得myApp-dataSource
、subsystemA-dataSource
、subsystemB-dataSource
三个名称指向了同一个对象,并且不会与任何其它定义产生冲突。
3.2 实例化Bean
待续
单词
Inversion of Control 控制反转(IoC)
dependency injection 依赖注入(DI)
sub-interface 子接口
enterprise-specific 企业特定的
superset 超集
metadata 元数据
instantiate 实例化
annotation 注解
fine-grained 细粒度
alias 别名