spring是目前使用最为广泛的Java框架之一。虽然spring最为核心是IOC和AOP,其中代码实现中很多设计模式得以应用,代码看起来简洁流畅,在日常的软件设计中很值得借鉴。以下是对一些设计模式的理解以及源码解析,希望能给大家对设计模式的理解有所帮助。
- 观察者模式:发布/订阅
更多设计模式更新中.....
(基于spring-4.3.23.RELEASE分析)
1、观察者模式: 发布/订阅
spring中ApplicationEvent事件通知就是观察者模式的变种,巧妙的利用事件驱动机制实现容器刷新。开发者可充分利用该机制,实现框架的深度定制。下面分为几点展开:
- spring中实现观察者设计模式的各个角色。
- 容器刷新中使用到的事件。
- 依据spring机制实现事件的发布/订阅 定制化框架。
(a) spring中实现观察者模式的各个角色:
ApplicationEventMulticaster是一个接口,定义了事件管理的基本行为,目前spring只有一个实现类和一个抽象类。这里先贴出定义理解各个角色的作用,后边一点点串联整个功能。
public interface ApplicationEventMulticaster {
/**
* 增加一个具体事件监听器
*/
void addApplicationListener(ApplicationListener<?> listener);
/**
* 增加一个事件监听器 以beanName形式
*/
void addApplicationListenerBean(String listenerBeanName);
/**
* 删除一个具体事件监听器
*/
void removeApplicationListener(ApplicationListener<?> listener);
/**
* 删除一个事件监听器 以beanName形式
*/
void removeApplicationListenerBean(String listenerBeanName);
/**
* 删除所有事件监听器
*/
void removeAllListeners();
/**
* 发布事件
*/
void multicastEvent(ApplicationEvent event);
/**
* 发布事件
*/
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}
ApplicationEvent是事件通知的媒介,也是消息传递的载体。这个类只是继承JDK原生的EventObject,约定为source的事件传递数据 只要理解其作用即可 比较简单所以贴出代码
/**
* Class to be extended by all application events. Abstract as it
* doesn't make sense for generic events to be published directly.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public abstract class ApplicationEvent extends EventObject {
/** use serialVersionUID from Spring 1.2 for interoperability. */
private static final long serialVersionUID = 7099057708183571937L;
/** System time when the event happened. */
private final long timestamp;
/**
* Create a new ApplicationEvent.
* @param source the object on which the event initially occurred (never {@code null})
*/
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
/**
* Return the system time in milliseconds when the event happened.
*/
public final long getTimestamp() {
return this.timestamp;
}
}
ApplicationEvent.java
/**
* <p>
* The root class from which all event state objects shall be derived.
* <p>
* All Events are constructed with a reference to the object, the "source",
* that is logically deemed to be the object upon which the Event in question
* initially occurred upon.
*
* @since JDK1.1
*/
public class EventObject implements java.io.Serializable {
private static final long serialVersionUID = 5516075349620653480L;
/**
* The object on which the Event initially occurred.
*/
protected transient Object source;
/**
* Constructs a prototypical Event.
*
* @param source The object on which the Event initially occurred.
* @exception IllegalArgumentException if source is null.
*/
public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");
this.source = source;
}
/**
* The object on which the Event initially occurred.
*
* @return The object on which the Event initially occurred.
*/
public Object getSource() {
return source;
}
/**
* Returns a String representation of this EventObject.
*
* @return A a String representation of this EventObject.
*/
public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
EventObject.java
ApplicationEventPublisher是对外暴露发布事件接口的定义 ApplicationContext容器实现该接口定义:
/**
* Interface that encapsulates event publication functionality.
* Serves as super-interface for {@link ApplicationContext}.
*
* @author Juergen Hoeller
* @author Stephane Nicoll
* @since 1.1.1
* @see ApplicationContext
* @see ApplicationEventPublisherAware
* @see org.springframework.context.ApplicationEvent
* @see org.springframework.context.event.EventPublicationInterceptor
*/
public interface ApplicationEventPublisher {
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an application event. Events may be framework events
* (such as RequestHandledEvent) or application-specific events.
* @param event the event to publish
* @see org.springframework.web.context.support.RequestHandledEvent
*/
void publishEvent(ApplicationEvent event);
/**
* Notify all <strong>matching</strong> listeners registered with this
* application of an event.
* <p>If the specified {@code event} is not an {@link ApplicationEvent},
* it is wrapped in a {@link PayloadApplicationEvent}.
* @param event the event to publish
* @since 4.2
* @see PayloadApplicationEvent
*/
void publishEvent(Object event);
}
ApplicationEventPublisher.java
SimpleApplicationEventMulticaster是AbstractApplicationEventMulticaster具体的实现,可以配置异步调用以解决效率问题以及事件调用异常的处理方式。主要的逻辑不复杂,很多实现的细节都隐藏在抽象类中,后续会有分析,很容易看得懂 接下来把目光聚集在AbstractApplicationEventMulticaster类。
AbstractApplicationEventMulticaster抽象类是分析的重点,该类实现了大部分的核心功能,包括监听者增加、删除、根据发布的事件类型匹配监听者,下面将结合容器刷新来串联整个过程。
(b) 容器刷新中使用到的事件机制。
(1)、AbstractApplicationContext中refresh()是整个spring容器刷新的入口, 如果你看过spring源码肯定非常熟悉这段代码:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// 获取容器,具体实现类重载加载所有bean定义
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// 初始化事件广播器 即上文的SimpleApplicationEventMulticaster 也可以重载该方法,注册自定义的广播器,实现定制化
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// 开始注册监听器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// 完成最后容器工作 发布第一个容器刷新完成事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
applicationEventMulticaster”的bean 则spring会使用定制化的事件广播器,否则会默认使用SimpleApplicationEventMulticaster。
/**
* Name of the ApplicationEventMulticaster bean in the factory.
* If none is supplied, a default SimpleApplicationEventMulticaster is used.
* @see org.springframework.context.event.ApplicationEventMulticaster
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
/**
* 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() + "]");
}
}
}
initApplicationEventMulticaster()
(3)、 此时事件广播器已经注册,再跟踪registerListeners()方法。 该方法主要完成所有监听者的注册、 触发最早起的事件通知,也是spring容器刷新阶段较早期触发的事件。
/**
* 注册所有的监听器
*/
protected void registerListeners() {
// Register statically specified listeners first.
// 注册容器创建时期静态赋值的监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 获取所有监听器的bean name 并注册所有beanName 以待后续查找使用
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
// 触发最早起的事件通知 并且只会触发一次
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
(4)、跟踪AbstractApplicationEventMulticaster#addApplicationListener 和 AbstractApplicationEventMulticaster#addApplicationListenerBean。 两个方法都比较简单,都是往监听器持有者defaultRetriever注册。
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
// 默认的监听器持有者
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
// 使用缓存方式加快解析效率
final Map<ListenerCacheKey, ListenerRetriever> retrieverCache =
new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>(64);
private ClassLoader beanClassLoader;
private BeanFactory beanFactory;
private Object retrievalMutex = this.defaultRetriever;
//.........
@Override
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.retrievalMutex) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
// 如果该类的代理类 需要将被代理类对象移除 防止产生两次通知的现象
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
@Override
public void addApplicationListenerBean(String listenerBeanName) {
synchronized (this.retrievalMutex) {
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
this.retrieverCache.clear();
}
}
//.........
}
View Code
(5)、再分析最关键的SimpleApplicationEventMulticaster#multicastEvent(final ApplicationEvent event, ResolvableType eventType) 根据发布的事件类别找到匹配的ApplicationListener集合,并触发通知。 串联了整个事件通知流程:
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
private Executor taskExecutor;
private ErrorHandler errorHandler;
// ..........
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
// 使用spring提供的ResolvableType类型解析类 匹配发布事件类型获得对应的监听器
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
// 可配置的异步处理 和 异常处理机制
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
return ResolvableType.forInstance(event);
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
private boolean matchesClassCastMessage(String classCastMessage, Class<?> eventClass) {
// On Java 8, the message starts with the class name: "java.lang.String cannot be cast..."
if (classCastMessage.startsWith(eventClass.getName())) {
return true;
}
// On Java 11, the message starts with "class ..." a.k.a. Class.toString()
if (classCastMessage.startsWith(eventClass.toString())) {
return true;
}
// On Java 9, the message used to contain the module name: "java.base/java.lang.String cannot be cast..."
int moduleSeparatorIndex = classCastMessage.indexOf('/');
if (moduleSeparatorIndex != -1 && classCastMessage.startsWith(eventClass.getName(), moduleSeparatorIndex + 1)) {
return true;
}
// Assuming an unrelated class cast failure...
return false;
}
}
View Code
跟进AbstractApplicationEventMulticaster#getApplicationListeners(ApplicationEvent event, ResolvableType eventType)获取所有符合条件的监听器
public abstract class AbstractApplicationEventMulticaster
implements ApplicationEventMulticaster, BeanClassLoaderAware, BeanFactoryAware {
private final ListenerRetriever defaultRetriever = new ListenerRetriever(false);
final Map<ListenerCacheKey, ListenerRetriever> retrieverCache =
new ConcurrentHashMap<ListenerCacheKey, ListenerRetriever>(64);
private ClassLoader beanClassLoader;
private BeanFactory beanFactory;
private Object retrievalMutex = this.defaultRetriever;
// 。。。。。。。。。
/**
* 根据事件类型找到匹配的监听器集合 充分缓存机制解决效率问题
*
* Return a Collection of ApplicationListeners matching the given
* event type. Non-matching listeners get excluded early.
* @param event the event to be propagated. Allows for excluding
* non-matching listeners early, based on cached matching information.
* @param eventType the event type
* @return a Collection of ApplicationListeners
* @see org.springframework.context.ApplicationListener
*/
protected Collection<ApplicationListener<?>> getApplicationListeners(
ApplicationEvent event, ResolvableType eventType) {
Object source = event.getSource();
Class<?> sourceType = (source != null ? source.getClass() : null);
ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);
// Quick check for existing entry on ConcurrentHashMap...
ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
if (retriever != null) {
return retriever.getApplicationListeners();
}
if (this.beanClassLoader == null ||
(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
// Fully synchronized building and caching of a ListenerRetriever
// 防止线程并发同步加载
synchronized (this.retrievalMutex) {
retriever = this.retrieverCache.get(cacheKey);
// 再次检查 防止并发导致多次计算
if (retriever != null) {
return retriever.getApplicationListeners();
}
retriever = new ListenerRetriever(true);
Collection<ApplicationListener<?>> listeners =
retrieveApplicationListeners(eventType, sourceType, retriever);
this.retrieverCache.put(cacheKey, retriever);
return listeners;
}
}
else {
// No ListenerRetriever caching -> no synchronization necessary
return retrieveApplicationListeners(eventType, sourceType, null);
}
}
/**
* 实际的事件类解析逻辑 结合上文提到的监听器持有者defaultRetriever 使用spring提供的ResolvableType类进行类型匹配
* 最后找到符合条件的监听器
* Actually retrieve the application listeners for the given event and source type.
* @param eventType the event type
* @param sourceType the event source type
* @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes)
* @return the pre-filtered list of application listeners for the given event and source type
*/
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) {
List<ApplicationListener<?>> allListeners = new ArrayList<ApplicationListener<?>>();
Set<ApplicationListener<?>> listeners;
Set<String> listenerBeans;
synchronized (this.retrievalMutex) {
listeners = new LinkedHashSet<ApplicationListener<?>>(this.defaultRetriever.applicationListeners);
listenerBeans = new LinkedHashSet<String>(this.defaultRetriever.applicationListenerBeans);
}
for (ApplicationListener<?> listener : listeners) {
if (supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
retriever.applicationListeners.add(listener);
}
allListeners.add(listener);
}
}
if (!listenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : listenerBeans) {
try {
Class<?> listenerType = beanFactory.getType(listenerBeanName);
if (listenerType == null || supportsEvent(listenerType, eventType)) {
ApplicationListener<?> listener =
beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
if (retriever != null) {
retriever.applicationListenerBeans.add(listenerBeanName);
}
allListeners.add(listener);
}
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
AnnotationAwareOrderComparator.sort(allListeners);
return allListeners;
}
protected boolean supportsEvent(Class<?> listenerType, ResolvableType eventType) {
if (GenericApplicationListener.class.isAssignableFrom(listenerType) ||
SmartApplicationListener.class.isAssignableFrom(listenerType)) {
return true;
}
ResolvableType declaredEventType = GenericApplicationListenerAdapter.resolveDeclaredEventType(listenerType);
return (declaredEventType == null || declaredEventType.isAssignableFrom(eventType));
}
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, Class<?> sourceType) {
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
/**
* Cache key for ListenerRetrievers, based on event type and source type.
*/
private static final class ListenerCacheKey implements Comparable<ListenerCacheKey> {
private final ResolvableType eventType;
private final Class<?> sourceType;
public ListenerCacheKey(ResolvableType eventType, Class<?> sourceType) {
this.eventType = eventType;
this.sourceType = sourceType;
}
// .......
}
/**
* 监听器持有者 实际从bean容器获得监听器的bean实例
* Helper class that encapsulates a specific set of target listeners,
* allowing for efficient retrieval of pre-filtered listeners.
* <p>An instance of this helper gets cached per event type and source type.
*/
private class ListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<ApplicationListener<?>>();
public final Set<String> applicationListenerBeans = new LinkedHashSet<String>();
private final boolean preFiltered;
public ListenerRetriever(boolean preFiltered) {
this.preFiltered = preFiltered;
}
public Collection<ApplicationListener<?>> getApplicationListeners() {
List<ApplicationListener<?>> allListeners = new ArrayList<ApplicationListener<?>>(
this.applicationListeners.size() + this.applicationListenerBeans.size());
allListeners.addAll(this.applicationListeners);
if (!this.applicationListenerBeans.isEmpty()) {
BeanFactory beanFactory = getBeanFactory();
for (String listenerBeanName : this.applicationListenerBeans) {
try {
ApplicationListener<?> listener = beanFactory.getBean(listenerBeanName, ApplicationListener.class);
if (this.preFiltered || !allListeners.contains(listener)) {
allListeners.add(listener);
}
}
catch (NoSuchBeanDefinitionException ex) {
// Singleton listener instance (without backing bean definition) disappeared -
// probably in the middle of the destruction phase
}
}
}
AnnotationAwareOrderComparator.sort(allListeners);
return allListeners;
}
}
}
AbstractApplicationEventMulticaster.java
(6)、最后finishRefresh()发布容器刷新成功事件
/**
* Finish the refresh of this context, invoking the LifecycleProcessor's
* onRefresh() method and publishing the
* {@link org.springframework.context.event.ContextRefreshedEvent}.
*/
protected void finishRefresh() {
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 发布容器刷新成功事件
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
View Code
(7)、跟踪上述的publishEvent(Object event, ResolvableType eventType)方法, spring容器实现了ApplicationEventPublisher接口 并委托事件广播器AbstractApplicationEventMulticaster完成事件到发布的过程。
// 发布一个 ApplicationEvent 事件
@Override
public void publishEvent(ApplicationEvent event) {
publishEvent(event, null);
}
// 发布一个ApplicationEvent事件 如果非ApplicationEvent类型事件,则默认被封装成PayloadApplicationEvent事件 传递实体
@Override
public void publishEvent(Object event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
// Decorate event as an ApplicationEvent if necessary
// 如果非ApplicationEvent类型事件,则默认被封装成PayloadApplicationEvent事件 传递实体
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
}
else {
applicationEvent = new PayloadApplicationEvent<Object>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else {
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
// 如果存在父亲容器则在容器发布该事件
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
源码分析到这里基本串联了整个流程,用一张图说明容器刷新时候事件调用链图,展示整个过程的数据流:
(c) 依据spring机制实现事件的发布/订阅 定制化框架。
实际项目中会有一些定制化的需求,spring强大之处不仅仅是Bean的托管,还提供很多拓展机制,例如Bean生命周期各个的接口 还有本文的主题ApplicationEvent发布特定的事件机制定制化框架。常见的spring内嵌Tomcat等Servlet容器提供Http服务 则优雅down机器很重要,需要等待所有业务请求处理完毕再关闭容器。 下面是一个简单的demo,也是拓展事件机制的基础:
实际传递DTO
@Data
@AllArgsConstructor
@ToString
public class EventDto {
private String name ;
}
发布的事件继承自 ApplicationEvent
@Getter
public class DemoApplicationEvent extends ApplicationEvent {
private String demo ;
public DemoApplicationEvent(String demo, EventDto eventDto) {
super(eventDto);
this.demo = demo ;
}
}
事件监听者
@Component
public class DemoApplicationListener implements ApplicationListener<DemoApplicationEvent> {
/**
* Handle an application event.
*
* @param event the event to respond to
*/
@Override
public void onApplicationEvent(DemoApplicationEvent event) {
System.out.println(event.getDemo() + " -- " + event.getSource());
}
}
启动springboot:
@SpringBootApplication
public class MqStarterApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(MqStarterApplication.class, args);
ctx.publishEvent(new DemoApplicationEvent("hello", new EventDto("pig")));
}
}
运行结果:
hello -- EventDto(name=pig)