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); } } } }; } }