「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」
1.前言
本文主要讲Spring IOC容器初始化过程中的onRefresh()方法 和 registerListeners() 方法,如想看之前的内容可查看 Spring IOC容器初始化原理分析 (第四节)
这两个方法都是在Spring IOC 容器初始化过程中 refresh()中调用的,其中 onRefresh()方法官方的定义是 初始化上下文其它特殊的bean , registerListeners() 方法,则见名知意就是检查并注册listener。
2.refresh()源码
如果需要复制代码,可前往Spring IOC容器初始化原理分析 (第一节)
3. onfresh() 方法讲解
首先点进源码看看,默认是一个空方法。
接着看看官方的说法,上面的注释说了它是一个模板方法,我们可以重写该方法,以添加特定于上下文的刷新工作。可以用来初始化上下文其他特殊bean,在单例实例化前调用。
这里官方没有实现,我们可以查看一下扩展包中的实现,这里主要是了解一下这个方法的作用。
如图我们以第一个org.springframework.web.context.support.AbstractRefreshableWebApplicationContext#onRefresh为例,点进去看看,源码如下:
这个方法主要是初始化主题的。我们接着点进去看看,它调用的是:org.springframework.ui.context.support.UiApplicationContextUtils#initThemeSource
- 在这个方法中,他首先判断容器中是否包含一个 名为 themeSource 的bean.
- 如果有的话,则从容器中取到这个bean,判断一下容器的parent 是否属于 ThemeSource 且 themeSource 是否属于 HierarchicalThemeSource ,如果是 则把 themeSource 转成 HierarchicalThemeSource 对象,设置一下它的 ParentThemeSource。返回themeSource
- 如果没有的话,则他会帮我们定义一个 HierarchicalThemeSource 类型的 themeSource 变量置为null,判断当前 context 的parent 是否属于 ThemeSource 。 如果是则把 themeSource 实例化成DelegatingThemeSource 对象,并设置下它的 ParentThemeSource,否则把它实例化成 ResourceBundleThemeSource 对象。最终返回themeSource。
总结:可以看到在这个方法中,它就给我们定义了一个特殊bean (themeSource)。所以这个方法的主要作用就是添加一些特殊bean。
4.registerListeners() 方法
老样子,我们接着进源码,这里为了大家更直观的看,我就直接把源码复制过来,直接在上面讲
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);
}
}
}
这里我把重点列出来细讲一下:
- getApplicationListeners() : 返回容器中静态的 ApplicationListener 集合,源码如下:
- getApplicationEventMulticaster() 拿到前面注册的 ApplicationEventMulticaster,如果没有就抛异常。 这里它的注册过程在 Spring IOC容器初始化原理分析 (第四节) 中 写的比较详细,这里就不讲了。
- addApplicationListener() 这就是添加一个 ApplicationListener
这里面它们面共同组成了 观察者设计模式, 当容器中的某些内部状态发生改变时,ApplicationEventMulticaster 会通知 ApplicationListener。
- ApplicationEventMulticaster 即(Subject 角色)
- AbstractApplicationEventMulticaster 或它的子类 SimpleApplicationEventMulticaster (Concrete Subject 角色) 实现了 ApplicationEventMulticaster 中的增加,移除,通知观察者的类
- ApplicationListener (Observer 角色) 提供了一个被调用的方法
- ApplicationListener的子类则是(Concrete Observer 角色) 不懂可以看上面的文章。
- 第二个for循环和第一个基本一样,不同的是一个是保存 ApplicationListener对象引用,一个是保存对象名这里我就不细讲了。
- this.earlyApplicationEvents :这里保存的容器早期发布的一些事件
- multicastEvent() :观察者模式中 Subject 角色 通知所有观察者的方法,当 earlyApplicationEvents 不为空时,ApplicationEventMulticaster就调用 multicastEvent(event),通知所有的观察者。源码如下:
@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());
}