Spring+EventBus实现异步事件
上代码
Maven依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.0-android</version>
</dependency>
ThreadPoolFactory
public final class ThreadPoolFactory {
private static final int DEFAULT_MAX_CONCURRENT = Runtime.getRuntime().availableProcessors() * 2;
private static final long DEFAULT_KEEP_ALIVE = 60L;
private static final int DEFAULT_SIZE = 1024;
private static final String DEFAULT_THREAD_POOL_NAME = "ProcessPool-{}-%d";
public static ExecutorService createDefThreadPool(){
return createInitThreadPool(DEFAULT_MAX_CONCURRENT, DEFAULT_MAX_CONCURRENT * 4, DEFAULT_KEEP_ALIVE,
TimeUnit.SECONDS, DEFAULT_SIZE, DEFAULT_THREAD_POOL_NAME, new ThreadPoolExecutor.CallerRunsPolicy());
}
public static ExecutorService createDefThreadPool(String poolName){
return createInitThreadPool(DEFAULT_MAX_CONCURRENT, DEFAULT_MAX_CONCURRENT * 4, DEFAULT_KEEP_ALIVE,
TimeUnit.SECONDS, DEFAULT_SIZE, poolName, new ThreadPoolExecutor.CallerRunsPolicy());
}
public static ExecutorService createDefThreadPool(int maxConcurrent, String poolName){
return createInitThreadPool(maxConcurrent, maxConcurrent * 4, DEFAULT_KEEP_ALIVE,
TimeUnit.SECONDS, DEFAULT_SIZE, poolName, new ThreadPoolExecutor.CallerRunsPolicy());
}
public static ExecutorService createInitThreadPool(final int coreConcurrent,
final int maxConcurrent,
final long keepAlive,
final TimeUnit timeUnit,
final int queueSize,
final String poolName,
final RejectedExecutionHandler handler
){
return TtlExecutors.getTtlExecutorService(new ThreadPoolExecutor(coreConcurrent, maxConcurrent, keepAlive, timeUnit,
new LinkedBlockingDeque<>(queueSize),
new ThreadFactoryBuilder().setNameFormat(poolName).build(),
handler
));
}
private ThreadPoolFactory(){}
}
IEventBus
public interface IEventBus {
void post(Object event);
void addConsumer(Object obj);
void removeConsumer(Object obj);
void scanConsumer(String packageName);
}
IEventConsumer
public interface IEventConsumer<T> {
void consumer(T event);
}
AbstractSpringEventBus
@Slf4j
public abstract class AbstractSpringEventBus implements IEventBus, ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
this.scanConsumer(null);
}
@Override
public void scanConsumer(String packageName) {
context.getBeansOfType(IEventConsumer.class).forEach((k,v)->{
this.addConsumer(v);
});
}
}
SpringEventBus
@Component
@Slf4j
public class SpringEventBus extends AbstractSpringEventBus implements SubscriberExceptionHandler {
private final EventBus eventBus;
public SpringEventBus() {
eventBus = new AsyncEventBus(
ThreadPoolFactory.createInitThreadPool(5, 10, 60, TimeUnit.SECONDS,
1024, "Event-Bus",
new ThreadPoolExecutor.CallerRunsPolicy()
)
, this
);
}
@Override
public void post(Object event) {
eventBus.post(event);
}
@Override
public void addConsumer(Object obj) {
eventBus.register(obj);
}
@Override
public void removeConsumer(Object obj) {
eventBus.unregister(obj);
}
@Override
public void handleException(Throwable exception, SubscriberExceptionContext context) {
log.error("user event handler exception", exception);
}
}
Test
@Data
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
}
TestEvent
@Slf4j
@Component
public class UnbindPhoneEvent implements IEventConsumer<Test> {
@Override
@Subscribe
public void consumer(Test event) {
log.info("监听到:{}",event.getName())
}
}
事件发布
@AllArgsConstructor
@RestController
public class TestController {
private final SpringEventBus springEventBus;
public void testMain(){
Test test = new Test();
test.setName("xx");
springEventBus.post(test);
}
}