• Spring ApplicationContext(十)finishRefresh


    ApplicationContext(十)finishRefresh

    Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)

    经过以上 11 步,ApplicationContext 的刷新工作基本完成,就剩下最后一点收尾的工作。

    在 Spring 中还提供了 Lifecycle 接口, Lifecycle 中包含 start/stop 方法,实现此接口后 Spring 会保证在启动的时候调用其 start 方法开始生命周期,并在 Spring 关闭的时候调用 stop 方法来结束生命周期,通常用来配置后台程序,在启动后一直运行(如对 MQ 进行轮询等)而 ApplicationContext 的初始化最后正是保证了这一功能的实现。

    protected void finishRefresh() {
        // Initialize lifecycle processor for this context.
        initLifecycleProcessor();
    
        // Propagate refresh to lifecycle processor first.
        getLifecycleProcessor().onRefresh();
    
        // Publish the final event.
        publishEvent(new ContextRefreshedEvent(this));
    
        // Participate in LiveBeansView MBean, if active.
        LiveBeansView.registerApplicationContext(this);
    }
    

    一、initLifecycleProcessor

    当 ApplicationContext 启动或停止时,它会通过 initLifecycleProcessor 来与所有声明的 bean 的周期做状态更新,而在 LifecycleProcessor 的使用前首先需要初始化。

    protected void initLifecycleProcessor() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
            this.lifecycleProcessor =
                    beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
        }
        else {
            DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
            defaultProcessor.setBeanFactory(beanFactory);
            this.lifecycleProcessor = defaultProcessor;
            beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
        }
    }
    

    二、onRefresh

    启动所有实现了 Lifecycle 接口的 bean

    public void onRefresh() {
        startBeans(true);
        this.running = true;
    }
    
    // Spring 内部用
    private void startBeans(boolean autoStartupOnly) {
        Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
        Map<Integer, LifecycleGroup> phases = new HashMap<Integer, LifecycleGroup>();
        for (Map.Entry<String, ? extends Lifecycle> entry : lifecycleBeans.entrySet()) {
            Lifecycle bean = entry.getValue();
            if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
                int phase = getPhase(bean);
                LifecycleGroup group = phases.get(phase);
                if (group == null) {
                    group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
                    phases.put(phase, group);
                }
                group.add(entry.getKey(), bean);
            }
        }
        if (phases.size() > 0) {
            List<Integer> keys = new ArrayList<Integer>(phases.keySet());
            Collections.sort(keys);
            for (Integer key : keys) {
                phases.get(key).start();
            }
        }
    }
    

    3. publishEvent

    当完成 ApplicationContext 初始化的时候,要通过 Spring 中的事件发布机制来发出 ContextRefreshedEvent 事件,以保证对应的监听器可以做进一步的逻辑处理。

    protected void publishEvent(Object event, ResolvableType eventType) {
        Assert.notNull(event, "Event must not be null");
    
        // 1. 如果 event 不是 ApplicationEvent,则需要进行封装成 PayloadApplicationEvent
        ApplicationEvent applicationEvent;
        if (event instanceof ApplicationEvent) {
            applicationEvent = (ApplicationEvent) event;
        }
        else {
            applicationEvent = new PayloadApplicationEvent<Object>(this, event);
            if (eventType == null) {
                eventType = ResolvableType.forClassWithGenerics(PayloadApplicationEvent.class, event.getClass());
            }
        }
    
        // 2. 发布事件 event,如果多播器懒加载,还没有初始化则将该事件先放到 earlyApplicationEvents 容器中
        //    等待多播器创建好了再发布事件 ???
        if (this.earlyApplicationEvents != null) {
            this.earlyApplicationEvents.add(applicationEvent);
        }
        else {
            getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
        }
    
        // 3. 父容器中也需要发布该事件 event
        if (this.parent != null) {
            if (this.parent instanceof AbstractApplicationContext) {
                ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
            }
            else {
                this.parent.publishEvent(event);
            }
        }
    }
    

    每天用心记录一点点。内容也许不重要,但习惯很重要!

  • 相关阅读:
    k8s Helm安装Prometheus Operator
    maven私有库神坑之:“Downloading: http://repo.maven.apache.org/maven2/”深坑!!!!!!坑害了一周时间
    docker java基础镜像
    helm安装EFK
    helm部署redis主从和哨兵模式
    k8s资源存储pv pvc 动态持久化存储StorageClass
    k8s service概述
    harbor镜像仓库原理和安装
    制作免费的https证书
    OpenStack点滴03-Neutron
  • 原文地址:https://www.cnblogs.com/binarylei/p/10423716.html
Copyright © 2020-2023  润新知