备注:不想基于Spring,就将spring的注解去掉就行。只不过需要自己new对象。基于spring,要源码可以找我哟。
定义事件发布者:该类的作用主要用于注册消费者,发布消息。异步处理消息:因此需要新开线程去处理。
package com.apeli.design;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
* subject
*
* @author liming
* @date 2023 06 07
*/
@Component
public class MessagePublisher {
/**
* 消费者列表
*/
private List<Consumer> consumerList;
/**
* 消息
*/
private Event event;
public MessagePublisher() {
this.consumerList = new ArrayList<>();
}
/**
* 发布事件
*
* @param event 事件
*/
public void publishEvent(Event event) {
this.event = event;
notifyAllObserver(event);
}
/**
* 注册消费者
*
* @param consumer 消费者
*/
public void register(Consumer consumer) {
consumerList.add(consumer);
}
/**
* 通知所有观察者
*
* @param event 状态
*/
private void notifyAllObserver(Event event) {
consumerList.forEach(consumer -> {
new Thread(() -> consumer.consumer(event)).start();
});
}
@Data
@AllArgsConstructor
public static class Event<T> {
private Integer eventId;
private T eventContent;
}
}
定义消费者: 定义事件发布器主要是为了在消费者被实例化时,自动加入事件发布器的consumerList中。这样做的好处是,如果我自定义的事件发布器和消费者都打上@compent的注解,在Spring初始化Bean时,事件监听器中会自动注册消费者。
package com.apeli.design;
/**
* 观察者模式
*
* @author liming
* @date 2023 06 07
*/
public abstract class Consumer {
/**
* 事件发布器
*/
protected MessagePublisher messagePublisher;
/**
*消费事件
* @param event 事件
*/
public abstract void consumer(MessagePublisher.Event event);
}
实现类:
package com.apeli.design;
import lombok.SneakyThrows;
import org.springframework.stereotype.Component;
/**
* 消费者
*
* @author liming
* @date 2023 06 07
*/
@Component
public class OrderConsumer extends Consumer {
public OrderConsumer(MessagePublisher messagePublisher) {
this.messagePublisher = messagePublisher;
messagePublisher.register(this);
}
@Override
@SneakyThrows
public void consumer(MessagePublisher.Event event) {
Thread.sleep(1000);
System.out.println("消费消息:"+event);
}
}
测试:
package com.apeli;
import com.apeli.design.MessagePublisher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan
public class SourceApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SourceApplication.class);
MessagePublisher messagePublisher = (MessagePublisher) context.getBean("messagePublisher");
messagePublisher.publishEvent(new MessagePublisher.Event(10,"消息"));
System.out.println("contine...");
}
}
截图: