• 初始化非延迟加载单例和finishRefresh


    初始化非延迟加载单例

    完成BeanFactory的初始化工作,其中包括ConversionService的设置、配置冻结以及非延迟加载的bean的初始化工作。

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
            // 为上下文初始化转换
            if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                    beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
                beanFactory.setConversionService(
                        beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
            }
    
            if (!beanFactory.hasEmbeddedValueResolver()) {
                beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
            }
    
            // 尽早初始化LoadTimeWeaverAware bean,以便尽早注册它们的转换器。
            String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
            for (String weaverAwareName : weaverAwareNames) {
                getBean(weaverAwareName);
            }
    
            // 停止使用临时类装入器进行类型匹配。
            beanFactory.setTempClassLoader(null);
    
            // 允许缓存所有bean定义元数据,冻结所有的bean定义,不再被修改
            beanFactory.freezeConfiguration();
    
            // 实例化所有剩余的(非延迟初始化)单例。
            beanFactory.preInstantiateSingletons();
        }

    首先我们来了解一下ConversionService类提供的作用。

    1.ConversionService的设置

    之前我们提到过使用自定义类型转换器从String转换为Date的方式,那么,在Spring中还提供了另一种转换方式:使用Converter。我们同样用一个简单的示例来了解Converter的使用方式。

    定义转换器:

    public class MyConverter implements Converter<String, Date> {
        @Override
        public Date convert(String source) {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                Date date = sdf.parse(source);
                return  date;
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return null;
        }
        //测试
        public static void main(String[] args){
            DefaultConversionService conversionService = new DefaultConversionService();
            conversionService.addConverter(new MyConverter());
            String date = "2019-01-04 12:23:34";
            System.out.println(conversionService.convert(date,Date.class));
        }
    }

    配置文件:

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
           <property name="converters">
               <list>
                   <bean class="com.joe.mytag.application.MyConverter"/>
               </list>
           </property>
       </bean>

    运行上述测试代码:

    Fri Jan 04 12:23:34 CST 2019

    通过以上功能我们看到了Converter以及ConversionService提供的便利服务,其中的配置就是在当前函数中被初始化的。

    2.冻结配置

    冻结所有的bean定义,说明注册的bean定义将不被修改或进行任何一步的处理。

    public void freezeConfiguration() {
            this.configurationFrozen = true;
            this.frozenBeanDefinitionNames = StringUtils.toStringArray(this.beanDefinitionNames);
        }

    3.初始化非延迟加载

    ApplicationContext实现的默认行为就是在启动时将所有单例bean提前进行实例化。提前实例化意味着作为初始化的一部分,ApplicationContext实例会创建并配置所有的单例bean。通常情况下这是一种好事,因为这样在配置中的任何错误就会立即被发现(否则的话可能要花费几个小时或者几天)。而这个实例化的过程就是在preInstantiateSingletons中完成的。

    public void preInstantiateSingletons() throws BeansException {
            if (logger.isTraceEnabled()) {
                logger.trace("Pre-instantiating singletons in " + this);
            }
    
            // 遍历副本以允许init方法注册新的bean定义。
            List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    
            // 触发所有非延迟单例bean的初始化…
            for (String beanName : beanNames) {
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                    if (isFactoryBean(beanName)) {
                        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                        if (bean instanceof FactoryBean) {
                            final FactoryBean<?> factory = (FactoryBean<?>) bean;
                            boolean isEagerInit;
                            if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                                isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                                ((SmartFactoryBean<?>) factory)::isEagerInit,
                                        getAccessControlContext());
                            }
                            else {
                                isEagerInit = (factory instanceof SmartFactoryBean &&
                                        ((SmartFactoryBean<?>) factory).isEagerInit());
                            }
                            if (isEagerInit) {
                                getBean(beanName);
                            }
                        }
                    }
                    else {
                        getBean(beanName);
                    }
                }
            }
    
            // 触发所有适用bean的初始化后回调。.
            for (String beanName : beanNames) {
                Object singletonInstance = getSingleton(beanName);
                if (singletonInstance instanceof SmartInitializingSingleton) {
                    final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                    if (System.getSecurityManager() != null) {
                        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                            smartSingleton.afterSingletonsInstantiated();
                            return null;
                        }, getAccessControlContext());
                    }
                    else {
                        smartSingleton.afterSingletonsInstantiated();
                    }
                }
            }
        }

    finishRefresh

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

    protected void finishRefresh() {
            // 清除上下文级资源缓存(例如扫描的ASM元数据)。
            clearResourceCaches();
    
            // 为此上下文初始化生命周期处理器。
            initLifecycleProcessor();
    
            // 首先将刷新传播到生命周期处理器。
            getLifecycleProcessor().onRefresh();
    
            // 发布最终事件。
            publishEvent(new ContextRefreshedEvent(this));
    
            
            LiveBeansView.registerApplicationContext(this);
        }

    1.initLifecycleProcessor 

     当ApplicationContext启动或者停止的时候,它会通过LifecycleProcessor来与所有声明的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);
                if (logger.isTraceEnabled()) {
                    logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
                }
            }
            else {
                DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
                defaultProcessor.setBeanFactory(beanFactory);
                this.lifecycleProcessor = defaultProcessor;
                beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
                if (logger.isTraceEnabled()) {
                    logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
                            "[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
                }
            }
        }

    2.onRefresh

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

    public void onRefresh() {
            startBeans(true);
            this.running = true;
        }
    private void startBeans(boolean autoStartupOnly) {
            Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
            Map<Integer, LifecycleGroup> phases = new HashMap<>();
            lifecycleBeans.forEach((beanName, bean) -> {
                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(beanName, bean);
                }
            });
            if (!phases.isEmpty()) {
                List<Integer> keys = new ArrayList<>(phases.keySet());
                Collections.sort(keys);
                for (Integer key : keys) {
                    phases.get(key).start();
                }
            }
        }

    3.publishEvent

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

    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
            Assert.notNull(event, "Event must not be null");
    
            // 如果需要,将事件装饰为ApplicationEvent
            ApplicationEvent applicationEvent;
            if (event instanceof ApplicationEvent) {
                applicationEvent = (ApplicationEvent) event;
            }
            else {
                applicationEvent = new PayloadApplicationEvent<>(this, event);
                if (eventType == null) {
                    eventType = ((PayloadApplicationEvent) applicationEvent).getResolvableType();
                }
            }
    
            // 如果可能的话,现在就进行多播——或者在初始化多播后进行延迟
            if (this.earlyApplicationEvents != null) {
                this.earlyApplicationEvents.add(applicationEvent);
            }
            else {
                getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
            }
    
            // 也通过父上下文发布事件…
            if (this.parent != null) {
                if (this.parent instanceof AbstractApplicationContext) {
                    ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
                }
                else {
                    this.parent.publishEvent(event);
                }
            }
        }

    参考:《Spring源码深度解析》 郝佳 编著:

    作者:Joe
    努力了的才叫梦想,不努力的就是空想,努力并且坚持下去,毕竟这是我相信的力量
  • 相关阅读:
    SpringBoot使用SpringSession和redis解决session共享问题(nginx反向代理)
    centos7中安装和配置nginx和keepalived
    定位
    css
    css美化
    html5
    列表,表格,媒体元素
    表单
    一期测试错题修改
    字符串
  • 原文地址:https://www.cnblogs.com/Joe-Go/p/10220878.html
Copyright © 2020-2023  润新知