spring作为粘合剂,其中IOC是它的基础,即控制反转,将项目中对对象的创建、依赖,交给IOC容器来完成。而每一个对象创建方式都各不相同,那么IOC要集中管理这一切,肯定不是一件简单的工作。本篇将介绍IOC容器整体启动的过程。

BeanFactory

IOC容器,是一个典型的工厂模式实现,BeanFactory是IOC最顶层的接口,规范了IOC最基础的功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public interface BeanFactory {

/**
* 用于配合FactoryBean的使用,当需要取得FactoryBean本身的对象时,需要加上该字符
*/
String FACTORY_BEAN_PREFIX = "&";


/**
* 从IOC容器中获取bean
*/
Object getBean(String name) throws BeansException;
<T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

/**
* 检索bean,是否存在于IOC容器中
*/
boolean containsBean(String name);
/**
* 是否为单例bean
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

/**
* 根据bean名字,返回bean的class对象
*/
@Nullable
Class<?> getType(String name) throws NoSuchBeanDefinitionException;

String[] getAliases(String name);
}

BeanFactory有三个重要的子接口:ListableBeanFactory、AutowireCapableBeanFactory、HierarchicalBeanFactory,最后都由DefaultListableBeanFactory来实现,之所以分别定义这么接口,是为了区别每一个接口的使用场合,对对象的数据访问做限制。例如

  • ListableBeanFactory 规范了bean的集合,表示bean可列表化。
  • AutowireCapableBeanFactory 规范了bean的行为,表示自动装配规则。
  • HierarchicalBeanFactory 规范了bean之间的关系,表示bean有继承关系,可能存在父bean。

我们通常说的ApplicationContext接口,是spring提供对BeanFactory功能增强的规范。spring提供了很多对IOC的实现,比如GenericApplicationContext、ClassPathXmlApplicationContext等。

BeanDefinition

每一个bean初始化的规则都不一样,我们通过xml或者注解配置bean的依赖关系后,spring会将其转换成BeanDefinition保存在IOC容器中,待bean真正创建的时候使用。所以BeanDefinition描述了整个bean的信息,包含依赖关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

/**
* 单例还是原型定义
*/
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;


/**
* bean的角色定义,表示用户定义bean、外部配置、完全与用户无关角色
*/
int ROLE_APPLICATION = 0;
int ROLE_SUPPORT = 1;
int ROLE_INFRASTRUCTURE = 2;

// 父类名字
void setParentName(@Nullable String parentName);
String getParentName();

// class名字
void setBeanClassName(@Nullable String beanClassName);
String getBeanClassName();

// 单例还是原型
void setScope(@Nullable String scope);
String getScope();

// 是否懒加载
void setLazyInit(boolean lazyInit);
boolean isLazyInit();

// 依赖关系
void setDependsOn(@Nullable String... dependsOn);
String[] getDependsOn();

void setAutowireCandidate(boolean autowireCandidate);
boolean isAutowireCandidate();
void setPrimary(boolean primary);
boolean isPrimary();
void setFactoryBeanName(@Nullable String factoryBeanName);
String getFactoryBeanName();
void setFactoryMethodName(@Nullable String factoryMethodName);
String getFactoryMethodName();
ConstructorArgumentValues getConstructorArgumentValues();
default boolean hasConstructorArgumentValues() {
return !getConstructorArgumentValues().isEmpty();
}
MutablePropertyValues getPropertyValues();
default boolean hasPropertyValues() {
return !getPropertyValues().isEmpty();
}

boolean isSingleton();
boolean isPrototype();
boolean isAbstract();
int getRole();
String getDescription();
String getResourceDescription();
BeanDefinition getOriginatingBeanDefinition();
}

一路看下来,spring的方法名字感觉挺符合中国人取名字的习惯,一看就能懂得那种。所以也没有写得过细。

BeanDefinitionReader

看上面BeanDefinition所描述的信息,就知道bean解析非常复杂,而BeanDefinition中所描述的信息,spring都需要留出可扩展的地方,保证足够灵活,而xml解析过程由BeanDefinitionReader来完成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface BeanDefinitionReader {
BeanDefinitionRegistry getRegistry();
ResourceLoader getResourceLoader();
ClassLoader getBeanClassLoader();
BeanNameGenerator getBeanNameGenerator();

/**
* 解析bean定义
*/
int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;
int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;
int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}

原理预透

IOC初始化,基本可以理解成两个动作。准备容器、加载BeanDefinition。而加载BeanDefinition大致过程分为:

  1. 由ResourceLoader来完成资源文件的定位
  2. 将Resource对象交给BeanDefinitionReader来完成解析
  3. 容器解析得到BeanDefinition后,需要在IOC中注册,由BeanDefinitionRegistry来完成

多说一句,BeanDefinitionRegistry的注册过程就是在IOC内部维护了一个Map,用来保存BeanDefinition,后续对bean的所有操作都围绕这个Map来完成。