Spring IOC容器初始化原理分析 (第五节)

「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战

1.前言

本文主要讲Spring IOC容器初始化过程中的onRefresh()方法 和 registerListeners() 方法,如想看之前的内容可查看 Spring IOC容器初始化原理分析 (第四节)

这两个方法都是在Spring IOC 容器初始化过程中 refresh()中调用的,其中 onRefresh()方法官方的定义是 初始化上下文其它特殊的bean , registerListeners() 方法,则见名知意就是检查并注册listener。

2.refresh()源码

如果需要复制代码,可前往Spring IOC容器初始化原理分析 (第一节)

refresh.jpg

  1. onfresh() 方法讲解

首先点进源码看看,默认是一个空方法。
图片.png
接着看看官方的说法,上面的注释说了它是一个模板方法,我们可以重写该方法,以添加特定于上下文的刷新工作。可以用来初始化上下文其他特殊bean,在单例实例化前调用。

这里官方没有实现,我们可以查看一下扩展包中的实现,这里主要是了解一下这个方法的作用。

图片.png

如图我们以第一个org.springframework.web.context.support.AbstractRefreshableWebApplicationContext#onRefresh为例,点进去看看,源码如下:

图片.png

这个方法主要是初始化主题的。我们接着点进去看看,它调用的是:org.springframework.ui.context.support.UiApplicationContextUtils#initThemeSource

图片.png
图片.png

  1. 在这个方法中,他首先判断容器中是否包含一个 名为 themeSource 的bean.
  2. 如果有的话,则从容器中取到这个bean,判断一下容器的parent 是否属于 ThemeSource 且 themeSource 是否属于 HierarchicalThemeSource ,如果是 则把 themeSource 转成 HierarchicalThemeSource 对象,设置一下它的 ParentThemeSource。返回themeSource
  3. 如果没有的话,则他会帮我们定义一个 HierarchicalThemeSource 类型的 themeSource 变量置为null,判断当前 context 的parent 是否属于 ThemeSource 。 如果是则把 themeSource 实例化成DelegatingThemeSource 对象,并设置下它的 ParentThemeSource,否则把它实例化成 ResourceBundleThemeSource 对象。最终返回themeSource。

总结:可以看到在这个方法中,它就给我们定义了一个特殊bean (themeSource)。所以这个方法的主要作用就是添加一些特殊bean。

4.registerListeners() 方法

老样子,我们接着进源码,这里为了大家更直观的看,我就直接把源码复制过来,直接在上面讲

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
scss复制代码protected void registerListeners() {
// 这里实际是挨个注册静态的监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}

// 从容器中获取所有实现了 ApplicationListener 接口的bean的name 放入applicationListenerBeans
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}

// Publish early application events now that we finally have a multicaster...
// 发布早期的监听器
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}

这里我把重点列出来细讲一下:

  1. getApplicationListeners() : 返回容器中静态的 ApplicationListener 集合,源码如下:

图片.png
图片.png

  1. getApplicationEventMulticaster() 拿到前面注册的 ApplicationEventMulticaster,如果没有就抛异常。 这里它的注册过程在 Spring IOC容器初始化原理分析 (第四节) 中 写的比较详细,这里就不讲了。

图片.png

  1. addApplicationListener() 这就是添加一个 ApplicationListener
    图片.png

这里面它们面共同组成了 观察者设计模式, 当容器中的某些内部状态发生改变时,ApplicationEventMulticaster 会通知 ApplicationListener。

  • ApplicationEventMulticaster 即(Subject 角色)
  • AbstractApplicationEventMulticaster 或它的子类 SimpleApplicationEventMulticaster
    (Concrete Subject 角色) 实现了 ApplicationEventMulticaster 中的增加,移除,通知观察者的类
  • ApplicationListener (Observer 角色) 提供了一个被调用的方法
  • ApplicationListener的子类则是(Concrete Observer 角色)
    不懂可以看上面的文章。
  1. 第二个for循环和第一个基本一样,不同的是一个是保存 ApplicationListener对象引用,一个是保存对象名这里我就不细讲了。
  2. this.earlyApplicationEvents :这里保存的容器早期发布的一些事件
  3. multicastEvent() :观察者模式中 Subject 角色 通知所有观察者的方法,当 earlyApplicationEvents 不为空时,ApplicationEventMulticaster就调用 multicastEvent(event),通知所有的观察者。源码如下:
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
typescript复制代码@Override
public void multicastEvent(ApplicationEvent event) {
// 调用 resolveDefaultEventType(event) 得到 ResolvableType对象
multicastEvent(event, resolveDefaultEventType(event));
}

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}

// 调用 ResolvableType 的静态方法 生成 ResolvableType
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}


public static ResolvableType forInstance(Object instance) {
Assert.notNull(instance, "Instance must not be null");
// 判断这个对象是否属于 ResolvableTypeProvider 如果属于 给它转换成 ResolvableType,当他不等于 null 时,返回
if (instance instanceof ResolvableTypeProvider) {
ResolvableType type = ((ResolvableTypeProvider) instance).getResolvableType();
if (type != null) {
return type;
}
}
// 否则的话直接调用 public static ResolvableType forClass(@Nullable Class<?> clazz) 返回
return ResolvableType.forClass(instance.getClass());
}

5.今天的分析就到这里了,后面没讲完的,我会继续在后续内容中更新。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%