本人本科毕业,21届毕业生,一年工作经验,简历专业技能如下,现根据简历,并根据所学知识复习准备面试。

记录日期:2022.1.4

大部分知识点只做大致介绍,具体内容根据推荐博文链接进行详细复习。

框架原理 - Spring(十四)之Spring IOC 源码finishRefresh()

AbstractApplicationContext#finishRefresh()

刷新完成工作,包括初始化 LifecycleProcessor,发布刷新完成事件等。

@SuppressWarnings("deprecation")
protected void finishRefresh() {
   
    // Clear context-level resource caches (such as ASM metadata from scanning).
    // 1. 清空上下文级别的资源缓存
    clearResourceCaches();

    // Initialize lifecycle processor for this context.
    // 2. 为此上下文初始化生命周期处理器
    initLifecycleProcessor();

    // Propagate refresh to lifecycle processor first.
    // 3. 首先将刷新完毕事件传播到生命周期处理器(触发isAutoStartup方法返回true的SmartLifecycle的start方法)
    getLifecycleProcessor().onRefresh();

    // Publish the final event.
    // 4. 推送上下文刷新完毕事件到相应的***
    publishEvent(new ContextRefreshedEvent(this));

    // Participate in LiveBeansView MBean, if active.
    if (!NativeDetector.inNativeImage()) {
   
        // 5. 注册MBean,通过JMX进行监控和管理
        LiveBeansView.registerApplicationContext(this);
    }
}

initLifecycleProcessor()

我们一起来看 finishRefresh()代码块的 2 中。

ApplicationContext 在启动或停止时, 它会通过 LifecycleProcessor 来与所有声明的Bean的周期做状态更新,这一步就是初始化LifecycleProcessor

需要注意的是,Spring会先从容器中获取BeanName为 "lifecycleProcessor" 的Bean实例,如果没有则使用Spring默认的DefaultLifecycleProcessor。所以开发者需要自定义LifecycleProcessor时一定需要将自己定义的LifecycleProcessor声明为 "lifecycleProcessor"

// LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";

protected void initLifecycleProcessor() {
   
    // 1. 获取当前 BeanFactory
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    
    // 2. 判断BeanFactory是否已经存在生命周期处理器
    if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
   
        // 2.1 如果已经存在,则将该bean赋值给lifecycleProcessor
        this.lifecycleProcessor =
            beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        if (logger.isTraceEnabled()) {
   
            logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
        }
    }
    else {
   
        // 2.2 如果不存在,则使用DefaultLifecycleProcessor
        DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
        defaultProcessor.setBeanFactory(beanFactory);
        this.lifecycleProcessor = defaultProcessor;
        // 并将DefaultLifecycleProcessor作为默认的生命周期处理器,注册到BeanFactory中
        beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
        if (logger.isTraceEnabled()) {
   
            logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
                         "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
        }
    }
}

getLifecycleProcessor().onRefresh()

我们一起来看 finishRefresh()代码块的 3 中。

LifecycleProcessor初始化完成之后,调用LifecycleProcessor接口的onRefresh()方法刷新所有实现了LifecycleBean

LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
   
    if (this.lifecycleProcessor == null) {
   
        throw new IllegalStateException(
            "LifecycleProcessor not initialized - " +
            "call 'refresh' before invoking lifecycle methods via the context: " +
            this);
    }
    return this.lifecycleProcessor;
}

// DefaultLifecycleProcessor 122
@Override
public void onRefresh() {
   
    startBeans(true);
    this.running = true;
}

// DefaultLifecycleProcessor 141
private void startBeans(boolean autoStartupOnly) {
   
    // 1.获取所有的Lifecycle bean
    Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
    // 将Lifecycle bean 按阶段分组,阶段通过实现Phased接口得到
    Map<Integer, LifecycleGroup> phases = new TreeMap<>();

    lifecycleBeans.forEach((beanName, bean) -> {
   
        /* autoStartupOnly=true代表是ApplicationContext刷新时容器自动启动 autoStartupOnly=false代表是通过显示的调用启动 */
        // 3.当autoStartupOnly=false,也就是通过显示的调用启动,会触发全部的Lifecycle;
        // 当autoStartupOnly=true,也就是ApplicationContext刷新时容器自动启动,只会触发isAutoStartup方法返回true的SmartLifecycle
        if (!autoStartupOnly ||
           		(
                    bean instanceof SmartLifecycle &&
                 	((SmartLifecycle) bean).isAutoStartup()
                )
           ) {
   
            // 3.1 获取bean的阶段值(如果没有实现Phased接口,则值为0)
            int phase = getPhase(bean);
            // 3.2 将bean添加到存放该阶段值的LifecycleGroup
            phases.computeIfAbsent(
                phase,
                // 3.3 如果该阶段值的LifecycleGroup为null,则新建一个
                p -> new LifecycleGroup(phase,
                                        this.timeoutPerShutdownPhase,
                                        lifecycleBeans,
                                        autoStartupOnly)
            ).add(beanName, bean);
        }
    });
    // 4.如果phases不为空
    if (!phases.isEmpty()) {
   
        // 4.1 调用LifecycleGroup中的所有Lifecycle的start方法
        phases.values().forEach(LifecycleGroup::start);
    }
}

这边还引入了 Phased 接口,这个接口类似于 Ordered 接口,只有一个方法用于返回一个 “阶段值”,范围为 Integer.MIN_VALUE ~ Integer.MAX_VALUE。在启动过程,“阶段值” 小的会被优先调用,而在关闭过程,“阶段值” 大的会被优先调用。

publishEvent()

我们一起来看 finishRefresh()代码块的 4 中。

当完成ApplicationContext容器刷新时,Spring通过事件发布机制发布ContextRefreshedEvent事件。以保证对应的***可以做进一步的逻辑处理。

Spring的publish-event使用的是监听者模式。

@Override
public void publishEvent(ApplicationEvent event) {
   
    publishEvent(event, null);
}

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
   
    Assert.notNull(event, "Event must not be null");

    // Decorate event as an ApplicationEvent if necessary
    // 1. 如果是一个ApplicationEvent,就强转,如果不是的话,包装成一个PayloadApplicationEvent
    ApplicationEvent applicationEvent;
    if (event instanceof ApplicationEvent) {
   
        applicationEvent = (ApplicationEvent) event;
    }
    else {
   
        applicationEvent = new PayloadApplicationEvent<>(this, event);
        if (eventType == null) {
   
            // 包装成一个PayloadApplicationEvent,并获取实际的带泛型的事件类型
          	// 比如PayloadApplicationEvent<MyEvent>
            eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
        }
    }

    // Multicast right now if possible - or lazily once the multicaster is initialized
    if (this.earlyApplicationEvents != null) {
   
        this.earlyApplicationEvents.add(applicationEvent);
    }
    else {
   
        // 2. 使用事件广播器广播事件到相应的***
        // 这里就是之前在initApplicationEventMulticaster初始化的事件广播器
        // 还有之前在registerListeners方法中注册的***
        getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    }

    // Publish event via parent context as well...
    // 3. 如果当前容易存在父容器,父容器也要发布事件
    if (this.parent != null) {
   
        if (this.parent instanceof AbstractApplicationContext) {
   
            ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
        }
        else {
   
            this.parent.publishEvent(event);
        }
    }
}

multicastEvent()

我们一起来看 publishEvent()代码块的 2 中。

它是如何使用事件广播器广播事件到相应的***的。

// SimpleApplicationEventMulticaster 135
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   
    ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    
    Executor executor = getTaskExecutor();
    // 1. getApplicationListeners:返回与给定事件类型匹配的应用***集合
    for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
   
        // 2. 返回此广播器的当前任务执行程序
        if (executor != null) {
   
            // 3.1 executor不为null,则使用executor调用***
            executor.execute(() -> invokeListener(listener, event));
        }
        else {
   
            // 3.2 否则,直接调用***
            invokeListener(listener, event);
        }
    }
}

可以发现,在通知监听者的时候,会去检查ApplicationEventMulticaster对象中是否配置了 Executor 执行器,如果配置了的话,会将 invokeListener(listener, event) 封装成一个线程可执行任务,然后给执行器执行。

invokeListener()

我们一起来看 invokeListener()代码块的 3.13.2 中。都是在 SimpleApplicationEventMulticaster 中实现的。

调用***的方法。

protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
   
    // 1. 返回此广播器的当前错误处理程序
    ErrorHandler errorHandler = getErrorHandler();
    if (errorHandler != null) {
   
        try {
   
            // 2.1 如果errorHandler不为null,则使用带错误处理的方式调用给定的***
            doInvokeListener(listener, event);
        }
        catch (Throwable err) {
   
            errorHandler.handleError(err);
        }
    }
    else {
   
        // 2.2 否则,直接调用调用给定的***
        doInvokeListener(listener, event);
    }
}

@SuppressWarnings({
   "rawtypes", "unchecked"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
   
    try {
   
        // 触发***的onApplicationEvent方法,参数为给定的事件
        listener.onApplicationEvent(event);
    }
    catch (ClassCastException ex) {
   
        String msg = ex.getMessage();
        if (msg == null || matchesClassCastMessage(msg, event.getClass()) ||
            (event instanceof PayloadApplicationEvent &&
             matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
   
            // Possibly a lambda-defined listener which we could not resolve the generic event type for
            // -> let's suppress the exception.
            Log loggerToUse = this.lazyLogger;
            if (loggerToUse == null) {
   
                loggerToUse = LogFactory.getLog(getClass());
                this.lazyLogger = loggerToUse;
            }
            if (loggerToUse.isTraceEnabled()) {
   
                loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
            }
        }
        else {
   
            throw ex;
        }
    }
}

自定义广播器的实现

我们可以自定义一个 ApplicationEventMulticaster

//需要注意的是,我们的名字一定要叫applicationEventMulticaster,否则不生效,回头看下源码就明白了
@Component("applicationEventMulticaster")
public class MyMulticaster extends SimpleApplicationEventMulticaster {
   

    @Override
    protected Executor getTaskExecutor() {
   
        // 这里可以按实际需求进行线程池的配置
        return new SimpleAsyncTaskExecutor();
    }

    // 这个方法主要配置错误处理,默认只会打一个警告级别的日志
    @Override
    protected ErrorHandler getErrorHandler() {
   
        return (() -> {
   
            System.out.println("出错了");
        });
    }
}

通过上面的配置后,我们所有的 publish-event 都会通过异步的机制去执行,但是我们想一个问题,有时候我们不想异步呢?一部分我们想同步,一部分想异步,这个时候怎么做呢?我们可以通过下面这种方式:

  1. 配置类上加注解 @EnableAsync
  2. 执行的方法上加注解 @Async
// 执行的方法上加@Async注解
@EventListener
@Async
public void on(MySecondEvent event) throws Exception {
   
	// ......
}

这样通过aop的方式,会将我们的方法采用异步的方式进行执行。我们没有配置线程池的时候可能会报错:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.core.task.TaskExecutor' available

不过我们方法还是会异步执行,这主要是下面这段代码:

protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
   
   if (beanFactory != null) {
   
      try {
   
      	// 在这里会抛出一个NoSuchBeanDefinitionException
         return beanFactory.getBean(TaskExecutor.class);
      }
      catch (NoUniqueBeanDefinitionException ex) {
   
         logger.debug("Could not find unique TaskExecutor bean", ex);
         try {
   
            return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
         }
         catch (NoSuchBeanDefinitionException ex2) {
   
            if (logger.isInfoEnabled()) {
   
               logger.info("More than one TaskExecutor bean found within the context, and none is named " +
                     "'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly " +
                     "as an alias) in order to use it for async processing: " + ex.getBeanNamesFound());
            }
         }
      }
       // 这里被捕获
      catch (NoSuchBeanDefinitionException ex) {
   
         logger.debug("Could not find default TaskExecutor bean", ex);
         try {
   
           // 我们也没有定义一个名字是DEFAULT_TASK_EXECUTOR_BEAN_NAME = "taskExecutor"
             // 的线程池
            return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
         }
         catch (NoSuchBeanDefinitionException ex2) {
   
            logger.info("No task executor bean found for async processing: " +
                  "no bean of type TaskExecutor and no bean named 'taskExecutor' either");
         }
         // Giving up -> either using local default executor or none at all...
      }
   }
    // 最后会返回一个null
   return null;
}

@Override
@Nullable
// 最后会返回一个SimpleAsyncTaskExecutor
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
   
   Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
   return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
}

自定义***的实现

如果我们想在 Spring IoC 容器构建完毕之后进行一些逻辑,就可以通过***来实现。

例如,创建一个自定义***,实现 ApplicationListener 接口,监听 ContextRefreshedEvent(上下文刷新完毕事件),并且将该***注册到 Spring IoC 容器即可。

@Component("myRefreshedListener")
public class MyRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {
   
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
   
        // ...
    }
}

这样,当 Spring 执行到 finishRefresh 方法时,就会将 ContextRefreshedEvent 事件推送到 MyRefreshedListener 中。

ContextRefreshedEvent 相似的还有:ContextStartedEventContextClosedEventContextStoppedEvent,有兴趣的可以自己看看这几个事件的使用场景。

当然,我们也可以自定义监听事件,只需要继承 ApplicationContextEvent 抽象类即可。