简单实现下监听
监听器提供了一种获取服务器运行状况、动态干预的方式,服务器在运行期间发生指定变化时及时介入干预。
首先我们定义一个监听事件的抽象类,所有事件都需要继承该类
1 public abstract class AbstractEvent { 2 //事件源 3 protected Object source; 4 5 public AbstractEvent(Object source) { 6 this.source = source; 7 } 8 9 public Object getSource() { 10 return source; 11 } 12 13 public void setSource(Object source) { 14 this.source = source; 15 } 16 17 }
我们使用一个接口来表示事件监听器,是个泛型接口,后面的类型E
表示当前监听器需要监听的事件类型,此接口中只有一个方法,用来实现处理事件的业务;其定义的监听器需要实现这个接口。
/** * 事件监听器 * * @param <E> 当前监听器感兴趣的事件类型 */ public interface EventListener <E extends AbstractEvent>{ /** * 此方法负责处理事件 * * @param event 要响应的事件对象 */ void onEvent(E event); }
事件广播器
- 讲白了就是在spring加载的时候去获取所有的EventListener
/** * 事件广播器: * 1.负责事件监听器的管理(注册监听器&移除监听器,将事件和监听器关联起来) * 2.负责事件的广播(将事件广播给所有的监听器,对该事件感兴趣的监听器会处理该事件) */ public interface EventMulticaster { /** * 广播事件给所有的监听器,对该事件感兴趣的监听器会处理该事件 * * @param event */ void multicastEvent(AbstractEvent event); /** * 添加一个事件监听器(监听器中包含了监听器中能够处理的事件) * * @param listener 需要添加监听器 */ void addEventListener(EventListener<?> listener); /** * 将事件监听器移除 * * @param listener 需要移除的监听器 */ void removeEventListener(EventListener<?> listener); }
到这里为止,一个简单的监听器的框架已经大致搭建完成了,下面我们看下他的简单的实现
首先是对于AbstractEvent,我们需要定义一个具体的事件,基于这个是事件去完成我们的监听
public class UserRegisterSuccessEvent extends AbstractEvent { //用户名 private String userName; /** * 创建用户注册成功事件对象 * * @param source 事件源 * @param userName 当前注册的用户名 */ public UserRegisterSuccessEvent(Object source, String userName) { super(source); this.userName = userName; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } }
其次,对于监听器我们需要在事件触发的时候具体的去执行我们的实现,并且我们需要监听器在spring中被具体的感知,所以需要添加注解@Component
@Component public class SendEmailOnUserRegisterSuccessListener implements EventListener<UserRegisterSuccessEvent>{ @Override public void onEvent(UserRegisterSuccessEvent event) { System.out.println( String.format("给用户【%s】发送注册成功邮件!", event.getUserName())); } }
然后,我们完成广播器的实现,把监听器放到容器中
/** * 事件广播器简单实现 */ public class SimpleEventMulticaster implements EventMulticaster{ private Map<Class<?>, List<EventListener>> eventObjectEventListenerMap = new ConcurrentHashMap<>(); @Override public void multicastEvent(AbstractEvent event) { List<EventListener> eventListeners = this.eventObjectEventListenerMap.get(event.getClass()); if (eventListeners != null) { for (EventListener eventListener : eventListeners) { eventListener.onEvent(event); } } } @Override public void addEventListener(EventListener<?> listener) { Class<?> eventType = this.getEventType(listener); List<EventListener> eventListeners = this.eventObjectEventListenerMap.get(eventType); if (eventListeners == null) { eventListeners = new ArrayList<>(); this.eventObjectEventListenerMap.put(eventType, eventListeners); } eventListeners.add(listener); } @Override public void removeEventListener(EventListener<?> listener) { Class<?> eventType = this.getEventType(listener); List<EventListener> eventListeners = this.eventObjectEventListenerMap.get(eventType); if (eventListeners != null) { eventListeners.remove(listener); } } /** * 获取事件监听器需要监听的事件类型 * * @param listener * @return */ protected Class<?> getEventType(EventListener listener) { ParameterizedType parameterizedType = (ParameterizedType) listener.getClass().getGenericInterfaces()[0]; Type eventType = parameterizedType.getActualTypeArguments()[0]; return (Class<?>) eventType; } }
接下来是最重要的,我们通过配置把获取监听器的List,把他放到容器里面,然后我们具体的服务可以去获取到这个容器从而进行广播,当事件发生的时候去触发具体的操作
public class ListenConfig { //这里是测试代码 这个bean会实列化两次,所以最好能在外面返回 static EventMulticaster eventPublisher = new SimpleEventMulticaster(); /** * 注册一个bean:事件发布者 * * @param eventListeners * @return */ @Bean public EventMulticaster eventMulticaster(List<EventListener> eventListeners) { //@1 if (eventListeners != null) { eventListeners.forEach(eventPublisher::addEventListener); } return eventPublisher; } /** * 注册一个bean:用户注册服务 * * @param eventMulticaster * @return */ @Bean public UserRegisterService userRegisterService(EventMulticaster eventMulticaster) { //@2 UserRegisterService userRegisterService = new UserRegisterService(); userRegisterService.setEventMulticaster(eventMulticaster); return userRegisterService; } }
业务代码
public class UserRegisterService { //事件发布者 private EventMulticaster eventMulticaster; //@0 /** * 注册用户 * * @param userName 用户名 */ public void registerUser(String userName) { //@1 //用户注册(将用户信息入库等操作) System.out.println(String.format("用户【%s】注册成功", userName)); //@2 //广播事件 UserRegisterSuccessEvent userRegisterSuccessEvent = new UserRegisterSuccessEvent(this, userName); this.eventMulticaster.multicastEvent(userRegisterSuccessEvent); //@3 } public EventMulticaster getEventMulticaster() { return eventMulticaster; } public void setEventMulticaster(EventMulticaster eventMulticaster) { this.eventMulticaster = eventMulticaster; } }
执行结果
2022-04-12 11:35:59.294 INFO 21068 --- [ main] c.example.listen.ListenApplicationTests : Started ListenApplicationTests in 2.975 seconds (JVM running for 3.862) 用户【bosssoft小王】注册成功 给用户【bosssoft小王】发送注册成功邮件! Disconnected from the target VM, address: '127.0.0.1:50071', transport: 'socket'