Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
49916bb7
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
49916bb7
编写于
4月 10, 2014
作者:
J
Juergen Hoeller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
SimpleApplicationEventMulticaster supports a configurable ErrorHandler strategy
Issue: SPR-11551
上级
14f9dbf7
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
118 addition
and
10 deletion
+118
-10
spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java
...work/context/event/SimpleApplicationEventMulticaster.java
+62
-10
spring-context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java
...framework/context/event/ApplicationContextEventTests.java
+56
-0
未找到文件。
spring-context/src/main/java/org/springframework/context/event/SimpleApplicationEventMulticaster.java
浏览文件 @
49916bb7
/*
* Copyright 2002-201
2
the original author or authors.
* Copyright 2002-201
4
the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -21,6 +21,7 @@ import java.util.concurrent.Executor;
import
org.springframework.beans.factory.BeanFactory
;
import
org.springframework.context.ApplicationEvent
;
import
org.springframework.context.ApplicationListener
;
import
org.springframework.util.ErrorHandler
;
/**
* Simple implementation of the {@link ApplicationEventMulticaster} interface.
...
...
@@ -32,7 +33,7 @@ import org.springframework.context.ApplicationListener;
*
* <p>By default, all listeners are invoked in the calling thread.
* This allows the danger of a rogue listener blocking the entire application,
* but adds minimal overhead. Specify an alternative
TaskE
xecutor to have
* but adds minimal overhead. Specify an alternative
task e
xecutor to have
* listeners executed in different threads, for example from a thread pool.
*
* @author Rod Johnson
...
...
@@ -43,6 +44,8 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
private
Executor
taskExecutor
;
private
ErrorHandler
errorHandler
;
/**
* Create a new SimpleApplicationEventMulticaster.
...
...
@@ -59,10 +62,11 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
/**
* Set the TaskExecutor to execute application listeners with.
* <p>Default is a SyncTaskExecutor, executing the listeners synchronously
* in the calling thread.
* <p>Consider specifying an asynchronous TaskExecutor here to not block the
* Set a custom executor (typically a {@link org.springframework.core.task.TaskExecutor})
* to invoke each listener with.
* <p>Default is equivalent to {@link org.springframework.core.task.SyncTaskExecutor},
* executing all listeners synchronously in the calling thread.
* <p>Consider specifying an asynchronous task executor here to not block the
* caller until all listeners have been executed. However, note that asynchronous
* execution will not participate in the caller's thread context (class loader,
* transaction association) unless the TaskExecutor explicitly supports this.
...
...
@@ -74,29 +78,77 @@ public class SimpleApplicationEventMulticaster extends AbstractApplicationEventM
}
/**
* Return the current
TaskE
xecutor for this multicaster.
* Return the current
task e
xecutor for this multicaster.
*/
protected
Executor
getTaskExecutor
()
{
return
this
.
taskExecutor
;
}
/**
* Set the {@link ErrorHandler} to invoke in case of an exception thrown
* from a listener.
* <p>Default is none, with a listener exception stopping the current
* multicast and getting propagated to the publisher of the current event.
* In case of a {@link #setTaskExecutor task executor} specified, each
* individual listener exception will get propagated to the executor but
* won't necessarily stop execution of other listeners.
* <p>Consider setting an {@link ErrorHandler} implementation that catches
* and logs exceptions (a la
* {@link org.springframework.scheduling.support.TaskUtils#LOG_AND_SUPPRESS_ERROR_HANDLER})
* or an implementation that logs exceptions while nevertheless propagating them
* ({@link org.springframework.scheduling.support.TaskUtils#LOG_AND_PROPAGATE_ERROR_HANDLER}).
* @since 4.1
*/
public
void
setErrorHandler
(
ErrorHandler
errorHandler
)
{
this
.
errorHandler
=
errorHandler
;
}
/**
* Return the current error handler for this multicaster.
* @since 4.1
*/
protected
ErrorHandler
getErrorHandler
()
{
return
this
.
errorHandler
;
}
@Override
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
public
void
multicastEvent
(
final
ApplicationEvent
event
)
{
for
(
final
ApplicationListener
listener
:
getApplicationListeners
(
event
))
{
for
(
final
ApplicationListener
<?>
listener
:
getApplicationListeners
(
event
))
{
Executor
executor
=
getTaskExecutor
();
if
(
executor
!=
null
)
{
executor
.
execute
(
new
Runnable
()
{
@Override
public
void
run
()
{
listener
.
onApplicationEvent
(
event
);
invokeListener
(
listener
,
event
);
}
});
}
else
{
invokeListener
(
listener
,
event
);
}
}
}
/**
* Invoke the given listener with the given event.
* @param listener the ApplicationListener to invoke
* @param event the current event to propagate
* @since 4.1
*/
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
protected
void
invokeListener
(
ApplicationListener
listener
,
ApplicationEvent
event
)
{
ErrorHandler
errorHandler
=
getErrorHandler
();
if
(
errorHandler
!=
null
)
{
try
{
listener
.
onApplicationEvent
(
event
);
}
catch
(
Throwable
err
)
{
errorHandler
.
handleError
(
err
);
}
}
else
{
listener
.
onApplicationEvent
(
event
);
}
}
...
...
spring-context/src/test/java/org/springframework/context/event/ApplicationContextEventTests.java
浏览文件 @
49916bb7
...
...
@@ -18,6 +18,7 @@ package org.springframework.context.event;
import
java.util.HashSet
;
import
java.util.Set
;
import
java.util.concurrent.Executor
;
import
org.aopalliance.intercept.MethodInvocation
;
import
org.junit.Test
;
...
...
@@ -33,6 +34,7 @@ import org.springframework.context.BeanThatListens;
import
org.springframework.context.support.AbstractApplicationContext
;
import
org.springframework.context.support.StaticApplicationContext
;
import
org.springframework.core.Ordered
;
import
org.springframework.scheduling.support.TaskUtils
;
import
org.springframework.tests.sample.beans.TestBean
;
import
static
org
.
junit
.
Assert
.*;
...
...
@@ -59,6 +61,60 @@ public class ApplicationContextEventTests {
verify
(
listener
).
onApplicationEvent
(
evt
);
}
@Test
public
void
simpleApplicationEventMulticasterWithTaskExecutor
()
{
@SuppressWarnings
(
"unchecked"
)
ApplicationListener
<
ApplicationEvent
>
listener
=
mock
(
ApplicationListener
.
class
);
ApplicationEvent
evt
=
new
ContextClosedEvent
(
new
StaticApplicationContext
());
SimpleApplicationEventMulticaster
smc
=
new
SimpleApplicationEventMulticaster
();
smc
.
setTaskExecutor
(
new
Executor
()
{
@Override
public
void
execute
(
Runnable
command
)
{
command
.
run
();
command
.
run
();
}
});
smc
.
addApplicationListener
(
listener
);
smc
.
multicastEvent
(
evt
);
verify
(
listener
,
times
(
2
)).
onApplicationEvent
(
evt
);
}
@Test
public
void
simpleApplicationEventMulticasterWithException
()
{
@SuppressWarnings
(
"unchecked"
)
ApplicationListener
<
ApplicationEvent
>
listener
=
mock
(
ApplicationListener
.
class
);
ApplicationEvent
evt
=
new
ContextClosedEvent
(
new
StaticApplicationContext
());
SimpleApplicationEventMulticaster
smc
=
new
SimpleApplicationEventMulticaster
();
smc
.
addApplicationListener
(
listener
);
RuntimeException
thrown
=
new
RuntimeException
();
doThrow
(
thrown
).
when
(
listener
).
onApplicationEvent
(
evt
);
try
{
smc
.
multicastEvent
(
evt
);
fail
(
"Should have thrown RuntimeException"
);
}
catch
(
RuntimeException
ex
)
{
assertSame
(
thrown
,
ex
);
}
}
@Test
public
void
simpleApplicationEventMulticasterWithErrorHandler
()
{
@SuppressWarnings
(
"unchecked"
)
ApplicationListener
<
ApplicationEvent
>
listener
=
mock
(
ApplicationListener
.
class
);
ApplicationEvent
evt
=
new
ContextClosedEvent
(
new
StaticApplicationContext
());
SimpleApplicationEventMulticaster
smc
=
new
SimpleApplicationEventMulticaster
();
smc
.
setErrorHandler
(
TaskUtils
.
LOG_AND_SUPPRESS_ERROR_HANDLER
);
smc
.
addApplicationListener
(
listener
);
doThrow
(
new
RuntimeException
()).
when
(
listener
).
onApplicationEvent
(
evt
);
smc
.
multicastEvent
(
evt
);
}
@Test
public
void
orderedListeners
()
{
MyOrderedListener1
listener1
=
new
MyOrderedListener1
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录