15-事件

事件监听器

准备发布事件逻辑

@Slf4j
@Component
static class MyService {

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void doBusiness() {
        log.warn("主线业务");
        // 主线业务完成后  需要做一些支线业务
//            log.warn("发送短信");
//            log.warn("发送邮件");
        applicationEventPublisher.publishEvent(new MyEvent("MyService#doBusiness"));
    }
}

准备事件

static class MyEvent extends ApplicationEvent {

    public MyEvent(Object source) {
        super(source);
    }

}

准备监听器-接口方式

@Slf4j
@Component
static class SmsApplicationListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        log.warn("发送短信");
    }
}

@Slf4j
@Component
static class EmailApplicationListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        log.warn("发送邮件");
    }
}

准备监听器-注解方式

@Slf4j
@Component
static class SmsService {
    @EventListener
    public void listener(MyEvent myEvent) {
        log.warn("发送短信");
    }
}

@Slf4j
@Component
static class EmailService {
    @EventListener
    public void listener(MyEvent myEvent) {
        log.warn("发送邮件");
    }
}

测试事件发布

@Configuration
public class TestEventListener {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestEventListener.class);

        //initApplicationListener(applicationContext);

        MyService myService = applicationContext.getBean(MyService.class);
        myService.doBusiness();

        applicationContext.close();
    }
}

异步发送-绑定线程池

@Bean
public ThreadPoolTaskExecutor executor() {
    ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    threadPoolTaskExecutor.setCorePoolSize(3);
    threadPoolTaskExecutor.setMaxPoolSize(10);
    threadPoolTaskExecutor.setQueueCapacity(100);
    return threadPoolTaskExecutor;
}

@Bean
public SimpleApplicationEventMulticaster applicationEventMulticaster(ThreadPoolTaskExecutor executor) {
    // 配置异步的事件发送器
    SimpleApplicationEventMulticaster applicationEventMulticaster = new SimpleApplicationEventMulticaster();
    applicationEventMulticaster.setTaskExecutor(executor);
    return applicationEventMulticaster;
}

模拟EventListener实现事件监听

/**
 * 写一个自定义注解  来测试内部是怎么实现事件监听的
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyEventListener {
}

@Slf4j
@Component
static class SmsService {
    @MyEventListener
    public void listener(MyEvent myEvent) {
        log.warn("发送短信");
    }
}

@Slf4j
@Component
static class EmailService {
    @MyEventListener
    public void listener(MyEvent myEvent) {
        log.warn("发送邮件");
    }
}

编码方式实现并放入容器(不推荐)

private static void initApplicationListener(AnnotationConfigApplicationContext applicationContext) {
    for (String beanName : applicationContext.getBeanDefinitionNames()) {
        // 遍历所有bean下面的所有方法
        Object bean = applicationContext.getBean(beanName);
        for (Method method : bean.getClass().getMethods()) {
            // 判断是否是MyEventListener
            if (method.isAnnotationPresent(MyEventListener.class)) {
                // 将当前方法包装层一个ApplicationListener bean
                ApplicationListener applicationListener = event -> {
                    System.out.println("当前事件:" + event);
                    // 获取方法上的事件类型 判断类型一致才可以处理
                    Class<?> eventType = method.getParameterTypes()[0];
                    if (eventType.isAssignableFrom(event.getClass())) {
                        try {
                            method.invoke(bean, event);
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                };
                // 将包装好的监听器  放入容器
                applicationContext.addApplicationListener(applicationListener);
            }
        }
    }
}

利用SmartInitializingSingleton机制(推荐)

@Bean
public SmartInitializingSingleton myEventListeners(AnnotationConfigApplicationContext applicationContext) {
    // SmartInitializingSingleton类是在所有单例对象完成后执行
    return () -> {
        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            Object bean = applicationContext.getBean(beanName);
            for (Method method : bean.getClass().getMethods()) {
                if (method.isAnnotationPresent(MyEventListener.class)) {
                    ApplicationListener applicationListener = event -> {
                        Class<?> eventType = method.getParameterTypes()[0];
                        if (eventType.isAssignableFrom(event.getClass())) {
                            try {
                                method.invoke(bean, event);
                            } catch (IllegalAccessException | InvocationTargetException e) {
                                e.printStackTrace();
                            }
                        }
                    };
                    applicationContext.addApplicationListener(applicationListener);
                }
            }
        }
    };
}

事件发布器

准备发布事件逻辑

@Slf4j
@Component
static class MyService {

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void doBusiness() {
        log.warn("主线业务");
        applicationEventPublisher.publishEvent(new MyEvent("MyService#doBusiness"));
    }
}

准备事件

static class MyEvent extends ApplicationEvent {
    public MyEvent(Object source) {
        super(source);
    }
}

准备监听器

@Slf4j
@Component
static class SmsApplicationListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        log.warn("发送短信");
    }
}

@Slf4j
@Component
static class EmailApplicationListener implements ApplicationListener<MyEvent> {
    @Override
    public void onApplicationEvent(MyEvent event) {
        log.warn("发送邮件");
    }
}

抽象一个空实现所有方法的ApplicationEventMulticaster

static class MyAbstractEventMulticaster implements ApplicationEventMulticaster {
    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {

    }

    @Override
    public void addApplicationListenerBean(String listenerBeanName) {

    }

    @Override
    public void removeApplicationListener(ApplicationListener<?> listener) {

    }

    @Override
    public void removeApplicationListenerBean(String listenerBeanName) {

    }

    @Override
    public void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate) {

    }

    @Override
    public void removeApplicationListenerBeans(Predicate<String> predicate) {

    }

    @Override
    public void removeAllListeners() {

    }

    @Override
    public void multicastEvent(ApplicationEvent event) {

    }

    @Override
    public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {

    }
}

准备线程池

@Bean
public ThreadPoolTaskExecutor executor() {
    ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
    threadPoolTaskExecutor.setCorePoolSize(3);
    threadPoolTaskExecutor.setMaxPoolSize(10);
    threadPoolTaskExecutor.setQueueCapacity(100);
    return threadPoolTaskExecutor;
}

自定义事件发布器

@Bean
public ApplicationEventMulticaster applicationEventMulticaster(AnnotationConfigApplicationContext applicationContext, ThreadPoolTaskExecutor executor) {
    // 配置自定义的事件发送器
    return new MyAbstractEventMulticaster() {

        //private List<ApplicationListener> applicationListenerList = new ArrayList<>();

        // GenericApplicationListener具备判断事件类型的能力
        private List<GenericApplicationListener> applicationListenerList = new ArrayList<>();

        // 收集事件监听器
        @Override
        public void addApplicationListenerBean(String listenerBeanName) {
            ApplicationListener applicationListener = applicationContext.getBean(listenerBeanName, ApplicationListener.class);
            ResolvableType interfaceEventType = ResolvableType.forClass(applicationListener.getClass()).getInterfaces()[0].getGeneric();
            System.out.println("当前事件监听器为:" + applicationListener + ", 能够处理的事件类型为:" + interfaceEventType);

            // 对事件进行包装  添加事件类型判断
            GenericApplicationListener genericApplicationListener = new GenericApplicationListener() {
                @Override
                public boolean supportsEventType(ResolvableType eventType) {
                    // 是否支持某时间类型     eventType为当前的事件类型
                    return interfaceEventType.isAssignableFrom(eventType);
                }

                @Override
                public void onApplicationEvent(ApplicationEvent event) {
                    // 支持异步
                    executor.submit(() -> applicationListener.onApplicationEvent(event));
                }
            };

            applicationListenerList.add(genericApplicationListener);
        }

        // 发布事件
        @Override
        public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
            for (GenericApplicationListener applicationListener : applicationListenerList) {
                if (applicationListener.supportsEventType(ResolvableType.forClass(event.getClass()))) {
                    applicationListener.onApplicationEvent(event);
                }
            }
        }
    };
}

测试

@Configuration
public class TestEventMulticaster {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestEventMulticaster.class);

        MyService myService = applicationContext.getBean(MyService.class);
        myService.doBusiness();

        applicationContext.close();
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

层巅余落日

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值