Spring高级 事件监听器 (三)@EventListener 解析原理

一、代码

1、自定义注解

package com.mangoubiubiu.annotation;

import java.lang.annotation.*;

@Target(value = {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)///注解可以在运行期的加载阶段被加载到Class对象中。那么在程序运行阶段,我们可以通过反射得到这个注解,并通过判断是否有这个注解或这个注解中属性的值,从而执行不同的程序代码段
@Documented//是被用来指定自定义注解是否能随着被定义的java文件生成到JavaDoc文档当中。
public @interface MyListener {
}

2、监听器

@Component
@Slf4j
public class SmsListener {
    @MyListener
    public void smsListener(MyEvent event) {
        log.info("发送短信");
    }
}

3、自定义扫描监听方法

package com.mangoubiubiu;

import com.mangoubiubiu.annotation.MyListener;
import com.mangoubiubiu.event.listener.SmsListener;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.lang.reflect.Method;

@MapperScan("com.mangoubiubiu.mapper")
@SpringBootApplication
@EnableScheduling//定时任务
public class BaseApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(BaseApplication.class, args);
        SmsListener smsListener = context.getBean(SmsListener.class);
        Method[] methods = SmsListener.class.getMethods();//得到所有公共方法
        for (Method method:methods) {
            if(method.isAnnotationPresent(MyListener.class)){
             ApplicationListener applicationListener  =  new ApplicationListener(){
                @Override
                public void onApplicationEvent(ApplicationEvent applicationEvent) {
                   try {
                       method.invoke(smsListener,applicationEvent);
                   }catch (Exception e){
                   e.printStackTrace();
                       //  System.out.println(e.getMessage());
                   }
                }
              };
             //把刚刚新生成的listener加入到Spring容器
             context.addApplicationListener(applicationListener);
            }
        }
    }
}

发现确实执行了 发短信的事件 但是其他事件类型执行报错了 (因为方法上的事件类型,和真正的事件类型不一致)

4、进阶 监听执行指定的事件类型

package com.mangoubiubiu;

import com.mangoubiubiu.annotation.MyListener;
import com.mangoubiubiu.event.listener.SmsListener;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.lang.reflect.Method;

@MapperScan("com.mangoubiubiu.mapper")
@SpringBootApplication
@EnableScheduling//定时任务
public class BaseApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(BaseApplication.class, args);
        SmsListener smsListener = context.getBean(SmsListener.class);
        Method[] methods = SmsListener.class.getMethods();//得到所有公共方法
        for (Method method:methods) {
            if(method.isAnnotationPresent(MyListener.class)){
             ApplicationListener applicationListener  =  new ApplicationListener(){
                @Override
                public void onApplicationEvent(ApplicationEvent applicationEvent) {
                    System.out.println(applicationEvent);
                    Class<?> eventType = method.getParameterTypes()[0];//监听器方法需要的事件类型
                    if(eventType.isAssignableFrom(applicationEvent.getClass())){
                        try {
                            method.invoke(smsListener,applicationEvent);
                        }catch (Exception e){
                            e.printStackTrace();
                            //  System.out.println(e.getMessage());
                        }
                    }
                }
              };
             //把刚刚新生成的listener加入到Spring容器
             context.addApplicationListener(applicationListener);
            }
        }
    }
}

发现只会执行 监听器传入的事件类型 没有报错

5、使用SmartInitializingSingleton 进行逻辑封装

package com.mangoubiubiu;

import com.mangoubiubiu.annotation.MyListener;
import com.mangoubiubiu.event.listener.SmsListener;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;

import java.lang.reflect.Method;

@MapperScan("com.mangoubiubiu.mapper")
@SpringBootApplication
@EnableScheduling//定时任务
public class BaseApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(BaseApplication.class, args);

    }

    @Bean
    public SmartInitializingSingleton smartInitializingSingleton(ConfigurableApplicationContext context){

        return new SmartInitializingSingleton() {
            @Override
            public void afterSingletonsInstantiated() {
                SmsListener smsListener = context.getBean(SmsListener.class);
                Method[] methods = SmsListener.class.getMethods();//得到所有公共方法
                for (Method method:methods) {
                    if(method.isAnnotationPresent(MyListener.class)){
                        ApplicationListener applicationListener  =  new ApplicationListener(){
                            @Override
                            public void onApplicationEvent(ApplicationEvent applicationEvent) {
                                System.out.println(applicationEvent);
                                Class<?> eventType = method.getParameterTypes()[0];//监听器方法需要的事件类型
                                if(eventType.isAssignableFrom(applicationEvent.getClass())){
                                    try {
                                        method.invoke(smsListener,applicationEvent);
                                    }catch (Exception e){
                                        e.printStackTrace();
                                        //  System.out.println(e.getMessage());
                                    }
                                }
                            }
                        };
                        //把刚刚新生成的listener加入到Spring容器
                        context.addApplicationListener(applicationListener);
                    }
                }
            }
        };
    }


}

 

 

posted @ 2022-06-12 15:29  KwFruit  阅读(446)  评论(0编辑  收藏  举报