Spring源码学习(四):容器的功能扩展·二

本文详细解析了Spring容器在启动过程中如何初始化MessageSource、ApplicationEventMulticaster、注册监听器,以及如何完成BeanFactory初始化和刷新过程。重点讨论了国际化、事件广播、监听器注册和Bean实例化等关键步骤,帮助读者深入理解Spring容器的内部工作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.initMessageSource

2.initApplicationEventMulticaster

3.registerListeners

4.finishBeanFactoryInitialization

5.finishRefresh


到目前,容器的启动过程还剩下下面几个方法:

this.initMessageSource(); //初始化消息源,用于国际化
this.initApplicationEventMulticaster(); //初始化应用程序的事件广播器
this.onRefresh(); //空方法,作为扩展点
this.registerListeners(); //查找并注册Listener Bean
this.finishBeanFactoryInitialization(beanFactory); //初始化剩余的单例
this.finishRefresh(); //完成刷新,并通知相关监听器

1.initMessageSource

MessageSource的作用是进行国际化,initMessageSource方法源码如下:

    protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
        if (beanFactory.containsLocalBean("messageSource")) {
            this.messageSource = (MessageSource)beanFactory.getBean("messageSource", MessageSource.class);
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource)this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    hms.setParentMessageSource(this.getInternalParentMessageSource());
                }
            }
        } else {
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(this.getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton("messageSource", this.messageSource);
        }

    }

该方法首先在容器中查找是否有名为“messageSource”的Bean,如果有,则获取它,假如它是HierarchicalMessageSource类型,则为其设置ParentMessageSource;如果没有,则新建一个DelegatingMessageSource对象,并为其创建单例实例。无论哪种情况,都会将其赋给类成员变量messageSource。从这段代码中,可以看到,假如说我们自己实现了一个MessageSource,在XML配置时,其id属性必须是“messageSource”,否则将不会生效,这里隐含的另一个限制就是,容器内只能有一个MessageSource生效。

HierarchicalMessageSource和DelegatingMessageSource都是MessageSource的子类,前者的两个实现类ResourceBundleMessageSource和ReloadableResourceBundleMessageSource,都是基于Java的ResourceBundle实现的,可以通过资源名加载国际化资源,ReloadableResourceBundleMessageSource可以在不重启程序的情况下更新国际化资源;DelegatingMessageSource主要用于父MessageSource。

需要提取出Message时,可以通过context.getMessage()方法,在ResourceBundleMessageSource中,该方法实际就是调用MessageSource的getMessageInternal方法,可以看到,MessageSource实质就是Locale和MessageFormat的封装:

    protected String getMessageInternal(@Nullable String code, @Nullable Object[] args, @Nullable Locale locale) {
        if (code == null) {
            return null;
        } else {
            if (locale == null) {
                locale = Locale.getDefault();
            }
            Object[] argsToUse = args;
            if (!this.isAlwaysUseMessageFormat() && ObjectUtils.isEmpty(args)) {
                String message = this.resolveCodeWithoutArguments(code, locale);
                if (message != null) {
                    return message;
                }
            } else {
                argsToUse = this.resolveArguments(args, locale);
                MessageFormat messageFormat = this.resolveCode(code, locale);
                if (messageFormat != null) {
                    synchronized(messageFormat) {
                        return messageFormat.format(argsToUse);
                    }
                }
            }
            Properties commonMessages = this.getCommonMessages();
            if (commonMessages != null) {
                String commonMessage = commonMessages.getProperty(code);
                if (commonMessage != null) {
                    return this.formatMessage(commonMessage, args, locale);
                }
            }
            return this.getMessageFromParent(code, argsToUse, locale);
        }
    }

2.initApplicationEventMulticaster

该方法的内容和initMessageSource的非常相似,同样限制了我们在XML中配置自定义实现时的id:

    protected void initApplicationEventMulticaster() {
        ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
        if (beanFactory.containsLocalBean("applicationEventMulticaster")) {
            this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean("applicationEventMulticaster", ApplicationEventMulticaster.class);
        } else {
            this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
            beanFactory.registerSingleton("applicationEventMulticaster", this.applicationEventMulticaster);
        }
    }

可以看到,容器的默认实现是SimpleApplicationEventMulticaster,当我们通过容器的publishEvent方法发布一个事件时,就会调用自身或父容器的来广播事件:

    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
        ...       
       this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
        if (this.parent != null) {
            if (this.parent instanceof AbstractApplicationContext) {
                ((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
            } else {
                this.parent.publishEvent(event);
            }
        }

    }

而multicastEvent方法就是遍历ApplicationListener列表,逐个触发(假如Executor不为空,则使用Executor异步触发):

    public void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType) {
        ResolvableType type = eventType != null ? eventType : this.resolveDefaultEventType(event);
        Iterator var4 = this.getApplicationListeners(event, type).iterator();
        while(var4.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var4.next();
            Executor executor = this.getTaskExecutor();
            if (executor != null) {
                executor.execute(() -> {
                    this.invokeListener(listener, event);
                });
            } else {
                this.invokeListener(listener, event);
            }
        }
    }

配置Executor的方法是,使用Spring的task标签:

<beans ... xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="...
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd">
    <task:executor id="executor" pool-size="5"/>
    <bean class="org.springframework.context.event.SimpleApplicationEventMulticaster">
        <property name="taskExecutor" ref="executor"></property>
    </bean>
</beans>

3.registerListeners

上一节说到,ApplicationEventMulticaster实现广播的方法就是,遍历在自己这里注册的监听器列表,逐个触发,所以registerListener方法就是向广播器注册监听器的过程。这里没有像之前的两个方法一样按照名字查找Bean,而是像PostProcessor一样按照类型查找,因此是不限数量,也不限id属性的:

    protected void registerListeners() {
        Iterator var1 = this.getApplicationListeners().iterator();
        while(var1.hasNext()) {
            ApplicationListener<?> listener = (ApplicationListener)var1.next();
            this.getApplicationEventMulticaster().addApplicationListener(listener);
        }
        String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false);
        String[] var7 = listenerBeanNames;
        int var3 = listenerBeanNames.length;
        for(int var4 = 0; var4 < var3; ++var4) {
            String listenerBeanName = var7[var4];
          this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            Iterator var9 = earlyEventsToProcess.iterator();
            while(var9.hasNext()) {
                ApplicationEvent earlyEvent = (ApplicationEvent)var9.next();
                this.getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

这里有一个过程是,假如有些事件是提前事件,即在Bean解析之后、监听器注册之前就已经实例化并触发的事件(例如Bean注册完成后会触发广播,虽然源码里是空实现,但是可以通过扩展的方式真正触发),就会在此先进行处理。

4.finishBeanFactoryInitialization

到上一步结束时,容器的扩展已经基本结束了,此时要做的就是对某些Bean进行预先实例化,同时冻结BeanDefinition,即在下次refresh之前,已经完成配置的Bean都不能再被修改了。

首先,检查容器是否配置了ConversionService,同样限定了id:

if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
    beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
}

接下来,如果没注册过后处理器,则注册一个StringValueResolver,主要作用是处理注解参数:

if (!beanFactory.hasEmbeddedValueResolver()) {
    beanFactory.addEmbeddedValueResolver((strVal) -> {
        return this.getEnvironment().resolvePlaceholders(strVal);
    });
}

然后实例化实现了LoadTimeWeaverAware接口的Bean:

String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
    getBean(weaverAwareName);
}

临时ClassLoader用来进行类型匹配,此处已经用不上了,可以置空:

beanFactory.setTempClassLoader(null);
beanFactory.freezeConfiguration();
beanFactory.preInstantiateSingletons();

freezeConfiguration用于设置标记位,表名设置冻结;

preInstantiateSingletons从名字来看,是提前实例化单例。首先会实例化所有没有设置init-lazy="true"的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);
        }
    }
}

FACTORY_BEAN_PREFIX是"&"。代码整体逻辑还是很清晰的,首先是进行判断,假如说bean是抽象的,那么肯定不能实例化,如果scope不是singleton,也没必要创建单例(prototype类型的bean随用随创建),如果是懒加载的,也不需要这时候实例化。然后判断bean是否是FactoryBean,即Bean是否实现了FactoryBean接口,用户可以通过实现该接口定制实例化Bean的逻辑,即Bean自身是否是一个工厂。同时还需要传入的Bean是SmartFactoryBean,且其isEagerInit方法返回true(接口中default实现返回false)。

然后触发所有Bean单例的初始化后的回调方法。这里要求单例实例必须是SmartInitializingSingleton类型,该接口只有一个afterSingletonsInstantiated方法。

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();
	    }
    }
}

5.finishRefresh

finishRefresh方法一共做了三件事:清理资源缓存、初始化并刷新生命周期处理器、发布容器刷新完毕事件。清理资源缓存实际就是执行其内部存储Resource对象的Map的clear方法,发布事件也不陌生,所以主要看生命周期处理器的相关内容。

Lifecycle接口包含start/stop方法,Spring容器启动时会执行其实现类的start方法,关闭时执行其stop方法。

该步骤由两个方法组成,第一个是initLifecycleProcessor方法,和initMessageSource、initApplicationEventMulticaster类似,都是先查找指定id“lifecycleProcessor”的Bean,有则赋给成员变量,否则实例化默认类型DefaultLifecycleProcessor,并为其创建和注册单例:

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

第二个是getLifecycleProcessor().onRefresh(),以DefaultLifecycleProcessor的实现为例,实际执行了startBeans方法:

    private void startBeans(boolean autoStartupOnly) {
        Map<String, Lifecycle> lifecycleBeans = this.getLifecycleBeans();
        Map<Integer, DefaultLifecycleProcessor.LifecycleGroup> phases = new HashMap();
        lifecycleBeans.forEach((beanName, bean) -> {
            if (!autoStartupOnly || bean instanceof SmartLifecycle && ((SmartLifecycle)bean).isAutoStartup()) {
                int phase = this.getPhase(bean);
                DefaultLifecycleProcessor.LifecycleGroup group = (DefaultLifecycleProcessor.LifecycleGroup)phases.get(phase);
                if (group == null) {
                    group = new DefaultLifecycleProcessor.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);
            Iterator var5 = keys.iterator();
            while(var5.hasNext()) {
                Integer key = (Integer)var5.next();
                ((DefaultLifecycleProcessor.LifecycleGroup)phases.get(key)).start();
            }
        }
    }

首先获取了实现Lifecycle接口的Bean,然后检查它们是否是SmartLifecycle类型且允许自动启动,是则获取该Bean所处的生命周期阶段,封装为LifecycleGroup对象并添加到Map中。然后执行每个Group的所有成员的start方法。

相应的,当容器关闭时,由于其注册了虚拟机的关闭钩子,所以会执行doClose方法进行安全关机,在这之中,我们也看到了LifecycleProcessor的身影:

protected void doClose() {
    ...
    if (this.lifecycleProcessor != null) {
        try {
            this.lifecycleProcessor.onClose();
        } catch (Throwable var2) {
            this.logger.warn("Exception thrown from LifecycleProcessor on context close", var2);
        }
    }
    ...
}

这里通过onClose方法,间接调用了stopBeans方法,其核心内容就是执行LifecycleGroup对象的stop方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值