上一篇Spring源码十:BeanPostProcess中,我们介绍了BeanPostProcessor是Spring框架提供的一个强大工具,它允许我们开发者在Bean的生命周期中的特定点进行自定义操作。通过实现BeanPostProcessor接口,开发者可以插入自己的逻辑,以增强或修改Bean的行为。这个接口在AOP、依赖注入和Bean管理等方面都有着广泛的应用。正确地使用BeanPostProcessor可以极大地提高Spring应用的灵活性和可扩展性。
通过上一篇文章的详细介绍,相信大家对BeanPostProcessor有了更深入的理解。在实际开发中,合理地应用BeanPostProcessor,可以帮助我们更好地控制和管理Bean的生命周期,实现复杂的业务需求。
接下来我们沿着上一篇的分析,回到refresh方法,接着往下看
initMessageSource
我们到initMessageSource方法中看下:
/*** Initialize the MessageSource.* Use parent's if none defined in this context.* 如果容器中已经注入id 为messageSource的bean* 如果没有,则初始化一个DelegatingMessageSource类型对象,注意一个细节,这里会将我初始化的Bean名称设置为messageSource* messageSource主要是用来处理国际化,就不继续讨论了*/protected void initMessageSource() {// 获取Spring beanFactory容器ConfigurableListableBeanFactory beanFactory = getBeanFactory();// 判断容器中,是否存id为messageSource的Beanif (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {// 获取messageSourcethis.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);// Make MessageSource aware of parent MessageSource.if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;if (hms.getParentMessageSource() == null) {// Only set parent context as parent MessageSource if no parent MessageSource// registered already.hms.setParentMessageSource(getInternalParentMessageSource());}}if (logger.isTraceEnabled()) {logger.trace("Using MessageSource [" + this.messageSource + "]");}}else {// Use empty MessageSource to be able to accept getMessage calls.// 初始化DelegatingMessageSourceDelegatingMessageSource dms = new DelegatingMessageSource();dms.setParentMessageSource(getInternalParentMessageSource());this.messageSource = dms;// 设置消息到容器中beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);if (logger.isTraceEnabled()) {logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");}}}
首先,`initMessageSource`方法的目的是确保Spring应用上下文(`ApplicationContext`)中有一个`MessageSource`组件。`MessageSource`是Spring国际化的核心接口,它提供了一种机制,允许应用程序根据用户的区域设置(Locale)来解析和提供相应的消息。
`MESSAGE_SOURCE_BEAN_NAME`是`AbstractApplicationContext`中定义的一个常量,其值为"defaultMessageSource"。这意味着,如果你要在XML配置文件中定义一个`MessageSource` bean,它的`id`属性必须设置为"defaultMessageSource",这样Spring容器才能正确地识别和获取它。
在`else`分支中,代码创建了一个`DelegatingMessageSource`实例。这是一个默认的`MessageSource`实现,它本身不包含任何消息,但可以作为一个代理(delegate),将消息解析委托给其父级`MessageSource`。如果没有任何`MessageSource`被定义,这个默认实例会被注册到Spring容器中,以避免在尝试解析消息时出现空指针异常。
国际化(i18n)是指应用程序能够适应并支持多种语言和文化。在软件开发中,这意味着用户界面、错误消息、日志信息等都应该能够以用户的本地语言和格式显示。Spring的`MessageSource`支持这一功能,它允许开发者定义不同语言环境的消息,并在运行时根据用户的`Locale`动态选择正确的消息。
虽然`MessageSource`在Spring中支持国际化,但在现代Java开发中,特别是使用Spring Boot时,国际化的处理方式可能会有所不同。Spring Boot提供了更简便的方式来管理资源和消息,例如使用`MessageSourceAutoConfiguration`和约定优于配置的原则。因此,直接使用Spring的`MessageSource`进行国际化可能不如使用Spring Boot的自动配置来得普遍。
总的来说,了解`MessageSource`的工作原理和配置方式是有价值的,但也要注意当前的最佳实践和趋势,特别是在使用现代Spring技术栈时。
ApplicationEventMulticaster
我们接着看refresh方法中的下一个方法
initApplicationEventMulticaster
我们进入initApplicationEventMulticaster方法中:
/*** Initialize the ApplicationEventMulticaster.* Uses SimpleApplicationEventMulticaster if none defined in the context.* @see org.springframework.context.event.SimpleApplicationEventMulticaster*/protected void initApplicationEventMulticaster() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {this.applicationEventMulticaster =beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);if (logger.isTraceEnabled()) {logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");}}else {this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);if (logger.isTraceEnabled()) {logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");}}}
在Spring框架中,`ApplicationEventMulticaster`是一个关键组件,负责管理和广播事件。`SimpleApplicationEventMulticaster`是`ApplicationEventMulticaster`的一个实现,它提供了基本的事件广播功能。
在Spring应用上下文初始化过程中,`initApplicationEventMulticaster`方法负责确保Spring容器中有一个`ApplicationEventMulticaster`的实例。这个实例可以通过检查Spring容器(`beanFactory`)来确定是否已经定义了一个名为`APPLICATION_EVENT_MULTICASTER_BEAN_NAME`(通常是"applicationEventMulticaster")的bean。如果存在,就直接获取并使用这个bean;如果不存在,就创建一个`SimpleApplicationEventMulticaster`的实例,并将其注册到Spring容器中。
`ApplicationEventMulticaster`与`ApplicationListener`密切相关。`ApplicationListener`是一个接口,任何实现了这个接口的bean都会被`ApplicationEventMulticaster`识别为监听器。当`ApplicationEventMulticaster`接收到一个`ApplicationEvent`(Spring框架中的事件对象)时,它会遍历所有注册的`ApplicationListener`,检查是否有监听器对这个事件感兴趣。
如果找到匹配的监听器,`ApplicationEventMulticaster`会调用监听器的`onApplicationEvent`方法来处理事件。这种设计模式被称为观察者模式,其中`ApplicationEventMulticaster`是主题(Subject),而`ApplicationListener`是观察者(Observer)。这种模式允许应用程序在发生特定事件时发布通知,而无需关心哪些组件会对此事件做出响应。
在现代的Spring应用程序中,事件驱动模型是一个强大的功能,它允许应用程序的不同部分通过发布和监听事件来进行解耦。例如,当一个服务完成了一个重要的业务操作时,它可以发布一个事件,而其他服务或组件可以监听这个事件并做出相应的处理,如更新缓存、发送通知等。这种模型提高了应用程序的灵活性和可扩展性。
示例
1. 自定义事件类
首先,定义一个自定义事件类MyselfEvent
,继承自ApplicationEvent
:
import org.springframework.context.ApplicationEvent;public class MyselfEvent extends ApplicationEvent {private String message;public MyselfEvent(Object source, String message) {super(source);this.message = message;}public String getMessage() {return message;}public void event() {// 处理事件逻辑System.out.println("Event method called with message: " + message);}
}
2. 自定义监听器
接着,创建一个监听器MyselfListener
,实现ApplicationListener<MyselfEvent>
接口:
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;@Component
public class MyselfListener implements ApplicationListener<MyselfEvent> {@Overridepublic void onApplicationEvent(MyselfEvent event) {// 处理事件event.event();System.out.println("Received event with message: " + event.getMessage());}
}
3. 配置监听器(XML配置)
将监听器注册到Spring上下文中,可以使用XML配置:
<!-- applicationContext.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 配置自定义监听器 --><bean id="myselfListener" class="com.example.MyselfListener"/>
</beans>
4. 发布事件
在Spring上下文初始化后,通过publishEvent
方法发布事件:
public class Main {public static void main(String[] args) {ApplicationContext context = new MyselfClassPathXmlApplicationContext("applicationContext.xml");JmUser jmUser = (JmUser)context.getBean("jmUser");MyselfEvent event = new MyselfEvent("source", "This is a custom event");context.publishEvent(event);// System.out.println(jmUser.getName());
// System.out.println(jmUser.getAge());}
}
5. 理解事件发布过程中的广播器作用
要深入理解事件发布过程中广播器ApplicationEventMulticaster
的作用,可以跟踪publishEvent
方法的执行过程。
ClassPathXmlApplicationContext
类的publishEvent
方法实际上是通过其父类AbstractApplicationContext
实现的:
public abstract class AbstractApplicationContext extends DefaultResourceLoaderimplements ConfigurableApplicationContext, DisposableBean {@Overridepublic void publishEvent(ApplicationEvent event) {getApplicationEventMulticaster().multicastEvent(event);}@Nullableprotected ApplicationEventMulticaster getApplicationEventMulticaster() {return this.applicationEventMulticaster;}
}
getApplicationEventMulticaster
方法返回一个ApplicationEventMulticaster
实例,通常是SimpleApplicationEventMulticaster
,用于将事件分发给已注册的监听器。
在SimpleApplicationEventMulticaster
的multicastEvent
方法中,事件会被分发给所有匹配的监听器:
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {@Overridepublic void multicastEvent(final ApplicationEvent event) {for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {listener.onApplicationEvent(event);}}
}
小结
通过以上步骤,我们实现了基于Spring内部广播器发布和处理自定义事件的过程,并深入理解了ApplicationEventMulticaster
在事件发布中的关键作用。广播器负责管理和调用注册的监听器,从而实现事件驱动的编程模型。