Spring中观察者模式的应用
Spring里的ApplicationListen相当于观察者;ApplicationEventPublisher可看作被观察对象。
当需要实现通知多个观察者的操作时可使用Spring里的ApplicationEventPublishe。观察者的操作可同步也可异步。
@Service
public class MyService {
/**
* Spring4.2之后,ApplicationEventPublisher 自动被注入到容器中,不再需要显示实现Aware接口。
*/
@Autowired
private ApplicationEventPublisher publisher;
public void doSomething(){
System.out.println(Thread.currentThread().getName()+ ":send the msg");
//发布通知
publisher.publishEvent(new MyEvent("content"));
}
}
/**
* 自定义事件
*/
public class MyEvent extends ApplicationEvent {
public MyEvent(Object source) {
super(source);
}
}
/**
* 自定义监听器(观察者)
*/
@Component
public class MyListener {
@EventListener
public void reciveMsg(MyEvent myEvent){
String msg = (String) myEvent.getSource();
System.out.println(Thread.currentThread().getName()+ ": recive msg --"+msg);
}
}
运行结果:service调用publisher的publishEven方法会将ApplicationEvent对象传给Multicast对象,Multicast对象可以根据ApplicationEvent拿到对应的监听器集合,迭代这个集合,执行每个监听器的操作。 这个过程是同步的,也就是说service必须等待观察者操作完毕才能继续运行。
当需要观察者异步执行时可做以下修改:
在容器中添加一个自定义的Executor,在启动类上添加@EnableAsync注解
@Configuration
@ComponentScan
@EnableAsync
public class MyConfig {
@Bean("myThreadPool")
public Executor getExecutor() {
ThreadFactory namedThreadFactory = r -> {
Thread thread = new Thread(r);
thread.setName("myThreadPool");
return thread;
};
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 线程池维护线程的最少数量
executor.setCorePoolSize(5);
// 线程池维护线程的最大数量
executor.setMaxPoolSize(10);
// 缓存队列
executor.setQueueCapacity(25);
//线程名
executor.setThreadFactory(namedThreadFactory);
// 线程池初始化
executor.initialize();
return executor;
}
}
在监听器方法上添加@Async注解,指定自己定义的Executor
/**
* 自定义监听器(观察者)
*/
@Component
public class MyListener {
@Async("myThreadPool")
@EventListener
public void reciveMsg(MyEvent myEvent){
String msg = (String) myEvent.getSource();
System.out.println(Thread.currentThread().getName()+ ": recive msg --"+msg);
}
}