为什么要用观察者模式?
当对一个对象的改变需要同时改变其它对象,而且并不知道具体有多少个对象待改变。
举个例子:博客更新文章时,有哪些地方需要同步更新?
1. 个人文章统计总数+1 2. 个人积分数+n 3. 关注者消息推送+1 4. 分类推送添加..
如果这些更新需要以插件形式加载或移除,就可以利用观察者模式。也就是后期再增加或移除相关功能模块,不需要太多工作。
写法
观察者模式自己写的话比较复杂,我们有现成的可以用就尽量不要重复造轮子。
主要有2种实现方式:Guava的EventBus和Spring Event。个人认为Spring的更加强大,这里介绍Spring Event。
@Data @Builder @AllArgsConstructor @NoArgsConstructor public class User { private Integer userId; private String userName; }
/** * <p color="orange"> * 基础事件发布类 * </p> * * @author BookSea * @date 2022/2/2 17:45 */ public abstract class BaseEvent<T> extends ApplicationEvent { /** * 该类型事件携带的信息 */ private T eventData; /** * * @param source 最初触发该事件的对象 * @param eventData 该类型事件携带的信息 */ public BaseEvent(Object source, T eventData) { super(source); this.eventData = eventData; } public T getEventData() { return eventData; } }
public class UserEvent extends BaseEvent<User>{ public UserEvent(Object source, User user) { super(source,user); } }
@Slf4j @Service public class UserListener { /* * @Async加了就是异步监听,没加就是同步 * 可以使用@Order定义监听者顺序,默认是按代码书写顺序 * 如果返回类型不为void,则会被当成一个新的事件,再次发布 * @EventListener注解在EventListenerMethodProcessor类被扫描 * 可以使用SpEL表达式来设置监听器生效的条件 * 监听器可以看做普通方法,如果监听器抛出异常,在publishEvent里处理即可 */ //@Async @Order(1) @EventListener(condition = "#userEvent.getEventData().getUserName().equals('小明')") public String lister1(UserEvent userEvent){ User user =userEvent.getEventData(); System.out.println(user.toString()); return "小米"; } @Async @Order(2) @EventListener public void lister3(UserEvent userEvent){ System.out.println("监听者2"); } @Async @Order(3) @EventListener public void lister2(String name){ System.out.println("我叫:"+name); } }
使用的时候注入ApplicationEventPublisher然后将事件发布即可。
@Resource private ApplicationEventPublisher applicationEventPublisher; applicationEventPublisher.publishEvent(new UserEvent(this, new User(1, "小明")));
IDEA可以直接跳转到对应的监听器