目录
2.initApplicationEventMulticaster
4.finishBeanFactoryInitialization
到目前,容器的启动过程还剩下下面几个方法:
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 !=