Spring-IOC原理(三)

前言

在上一篇博文《Spring-IOC原理(二)》中分析了AnnotationConfigApplicationContext构造方法中的this()方法,也知道了在这个方法中主要注册了一些Spring初始化必要的Bean,并且也创建了我们的容器对象。接下来继续看一下AnnotationConfigApplicationContext构造方法中的register()方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
/** 这里会实例化BeanDefinitionReader和BeanDefinitionScanner,并注册一些框架初始化必要的Bean
* 调用无参构造函数,会先调用父类GenericApplicationContext的构造函数,父类构造函数中就是初始化
* DefaultListableBeanFactory,并且赋值给beanFactory。
* 在本类的构造函数中,初始化了一个读取器reader = new AnnotatedBeanDefinitionReader(this);
* 和一个扫描器scanner = new ClassPathBeanDefinitionScanner(this);
* 扫描器scanner的用出不是很大,它仅仅是我们外部手动调用.scan()方法时才会用到的,常规方式是不会用到scanner
*/
this();
/** 注册Bean
* 把传入的类进行注册,这里会有两种方式,一种是传入配置类,一种是传入bean。
* 这里spring会把传统的带有@Configuration注解的类称之为FULL配置类,不带@Configuration注解但是带有@Component
* @Import@ImportResource@Server@ComponentScan 等注解的类称之为Lite配置类
* 我们这里先把带有@Configuration注解的称之为传统配置类,不带该注解的称之为普通类
*/
register(componentClasses);
/** 刷新 */
refresh();
}

一、register方法分析

老办法,进入register(componentClasses)

1
2
3
4
5
@Override
public void register(Class<?>... componentClasses) {
Assert.notEmpty(componentClasses, "At least one component class must be specified");
this.reader.register(componentClasses);
}

是一个重写方法,在方法中又调用了register(componentClasses);这次是调用reader中的register。先来看看reader是什么东西?

1
2
3
4
/**
* 注解bean定义读取器,主要作用是读取被注解标记的bean
*/
private final AnnotatedBeanDefinitionReader reader;

看到这个,脑海中突然想到,我们在this()方法中不是初始化过一个AnnotatedBeanDefinitionReader吗!没错这个reader就是在this()中初始化完成创建的,几乎之后的用的reader,也是这个。既然知道它的来来龙去脉了,那就继续往下走,进到

1
this.reader.register(componentClasses)

方法中。

1
2
3
4
5
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}

在这个方法中,依次遍历componentClasses,并将遍历出的类通过registerBean方法中。进入registerBean(componentClasses)方法中具体看看是怎么做的。

1
2
3
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}

又被Spring代码搞恶心了,这TM套了这么多层还没有进入。高手都是这样子写代码的吗??后来才知道其实在Spring源码中,不管嵌套多少次,最终真正干活的方法只有是doXXX()的方法。好吧继续进到doRegisterBean()方法中。

1.1、doRegisterBean方法分析

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {

/**
* AnnotatedGenericBeanDefinition一种数据结构,用来描述Bean的,这里的作用就是把传入的标记了注解的类转为
* AnnotatedGenericBeanDefinition数据结构,类里面有一个getMetadata方法,可以拿到类上面的注解信息
*/
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
/**
* 判断是否需要跳过注解,spring中有@Condition注解,当不满足条件,这个Bean就不会被解析
*/
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}

abd.setInstanceSupplier(supplier);
/**
* 解析bean的作用域,如果没有设置的话,默认是单例
*/
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
/**
* 获取bean名字
*/
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

/**
* 解析通用注解,填充到AnnotatedGenericBeanDefinition,解析的注解为@Lazy@Primary,@DependsOn@Role@Description
*/
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
/**
* 限定符处理,不是特指@Qualifier注解,也有可能是@Primary,或者@Lazy,或者是其他,如果以常规方式去初始化spring
* ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationMain.class);
* qualifier永远都是空的,包括上面的name和instanceSupplier都是同样的道理
* 但是spring提供了其他方式去注册bean,就可能传入了
*/
if (qualifiers != null) {
/**
* 可以传入qualifier数组,所以这里循环处理
*/
for (Class<? extends Annotation> qualifier : qualifiers) {
/**
* 优先处理@Primary注解
*/
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
/**
* 再处理@Lazy注解
*/
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
/**
* 最后处理其他注解
*/
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
/**
* 将AnnotatedGenericBeanDefinition和beanName封装到一个对象中BeanDefinitionHolder
*/
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
/**
* 注册。最终调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,DefaultListableBeanFactory会维护一系列的信息
* 比如beanDefinitionNames,beanDefinitionMap。
* beanDefinitionNames是一个List<String> 用来存放bean的名字
* beanDefinitionMap是一个Map<String,BeanDefinition>
*/
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

详细看一下上面代码。

1.1.1、 初始化AnnotatedGenericBeanDefinition

首先是创建了一个AnnotatedGenericBeanDefinition,它其实可以看做是一种数据结构,里面会包含一些注解信息

1
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);

在这里创建AnnotatedGenericBeanDefinition的作用主要是吧传入的标记了注解的类封装为AnnotatedGenericBeanDefinition类型,然后可以通过AnnotatedGenericBeanDefinition中的getMetadata()方法来拿到类上面的注解信息。

1.1.2、shouldSkip()判断是否跳过

接下类会判断是否需要跳过注解。在Spring中有一个@Confition注解,当不满足该注解表达式中条件时,这个Bean就不会被解析

1
2
3
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}

shouldSkip()方法中主要是解析带有@Conditional注解的类,如果没有注解这个注解,则直接返回false,否则会循环递归去解析带有该注解的类;并将所有带有该注解的类元信息拿到,并遍历渠道过滤条件,然后将过滤条件封装为Condition加入到conditions集合中;然后进行排序,之后会遍历我们刚刚保存的条件集合conditions ,通过matchs()方法匹配到符合过滤条件的bean,返回true

1.1.3、解析bean作用域

1
2
3
4
5
/**
* 解析bean的作用域,如果没有设置的话,默认是单例
*/
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());

这里bean的作用域默认是单例,当然可以通过@Scope(scopeName = "")注解来指定作用域,是singleton还是prototype

1.1.4、解析通用注解

通过AnnotationConfigUtils.processCommonDefinitionAnnotations(abd)来解析通用注解,例如@Lazy@Primary@DependsOn@Role@Description注解。然后处理解析到的注解

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
if (qualifiers != null) {
/**
* 可以传入qualifier数组,所以这里循环处理
*/
for (Class<? extends Annotation> qualifier : qualifiers) {
/**
* 优先处理@Primary注解
*/
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
/**
* 再处理@Lazy注解
*/
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
/**
* 最后处理其他注解
*/
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}

从上述代码我们可以看出,其实@Lazy@Primary@DependsOn@Role@Description在处理的时候是有优先级的,如果一个类中以上几个注解都标注了,那么优先级依次是:@Primary > @Lazy > 其他注解

1.1.5、通过registerBeanDefinition()注册spring需要的基础bean

1
2
3
4
5
6
7
/**
* 注册。最终调用DefaultListableBeanFactory中的registerBeanDefinition方法去注册,DefaultListableBeanFactory会维护一系列的信息
* 比如beanDefinitionNames,beanDefinitionMap。
* beanDefinitionNames是一个List<String> 用来存放bean的名字
* beanDefinitionMap是一个Map<String,BeanDefinition>
*/
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);

最终通过调用DefaultListableBeanFactory类中的registerBeanDefinition()来完成基础bean的注册,这个方法的调用链很深,我们先点进到registerBeanDefinition()方法中看看。

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
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {

// Register bean definition under primary name.
/**
* 获取bean的名字
*/
String beanName = definitionHolder.getBeanName();
/**
* 注册bean
*/
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

/**
* 如果有别名,注册别名
*/
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}

registerBeanDefinition()方法中先获取了bean名字,然后通过调用registry.registerBeanDefinition(beanName,beanDefinition)来真正完成注册,这里的registryDefaultListableBeanFactory实现子类,所以我们到DefaultListableBeanFactory类中找到registerBeanDefinition()方法,如下:

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");

if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}

/** 先从beanDefinitionMap一级缓存中获取bean */
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
/** 如果一级缓存中有bean */
if (existingDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
/** 将bean设置到一级缓存 */
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
/**
* beanDefinitionMap是Map<String,BeanDefinition>,这里把beanName作为key,beanDefinition作为value
*/
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}

if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
else if (isConfigurationFrozen()) {
clearByTypeCache();
}
}

这里首先会判断beanDefinitionMap缓存中是否存在bean,第一次进来肯定是不存在的,所以第一次进来必定会进入else分支,在else分支中,为了避免重复创建,首先会通过hasBeanCreationStarted()来判断是否已经创建。第一次的话这里肯定也是没有创建,所以也不会进入到if中,来到else将beanDefinition放入beanDefinitionMap中,beanName放入beanDefinitionNames集合中。最后开看一些beanDefinitionMapbeanDefinitionNames的结构

1
2
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

从代码中可以看出,beanDefinitionMap是一个Map,并且key是beanName,value是BeanDefinitionbeanDefinitionNames是一个集合,并且是线程可见变量集合,用来保存beanName

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!

请我喝杯咖啡吧~

支付宝
微信