zoukankan      html  css  js  c++  java
  • 初始化非延迟加载单例和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
    努力了的才叫梦想,不努力的就是空想,努力并且坚持下去,毕竟这是我相信的力量
  • 相关阅读:
    IOS Charles(代理服务器软件,可以用来拦截网络请求)
    Javascript中addEventListener和attachEvent的区别
    MVC中实现Area几种方法
    Entity Framework Code First 中使用 Fluent API 笔记。
    自定义JsonResult解决 序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用
    序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用
    An entity object cannot be referenced by multiple instances of IEntityChangeTracker 的解决方案
    Code First :使用Entity. Framework编程(8) ----转发 收藏
    Code First :使用Entity. Framework编程(6) ----转发 收藏
    Code First :使用Entity. Framework编程(5) ----转发 收藏
  • 原文地址:https://www.cnblogs.com/Joe-Go/p/10220878.html
Copyright © 2011-2022 走看看