栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【springboot】事件与事件监听器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【springboot】事件与事件监听器

参考:

Spring ApplicationListener:https://blog.csdn.net/liyantianmin/article/details/81017960

Spring Boot 启动事件顺序:https://blog.csdn.net/qq_42948241/article/details/114587189

springboot事件监听器:https://www.jianshu.com/p/3478c9ea16c0

BeanPostProcessor:https://www.jianshu.com/p/369a54201943

使用观察者模式可以实现事件监听。【发布(添加事件监听,触发事件)-订阅(添加事件)】

spring ApplicationListener

事件可以自定义、监听也可以自定义,根据业务处理。Spring 内置事件:

事件描述
ContextRefreshedEventApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 refresh() 方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用
ContextStartedEvent当使用 ConfigurableApplicationContext (ApplicationContext子接口)接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。
ContextStoppedEvent当使用 ConfigurableApplicationContext 接口中的 stop() 停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
ContextClosedEvent当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
RequestHandledEvent这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。只能应用于使用DispatcherServlet的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。
内置事件
@Component
public class TestApplicationListener implements ApplicationListener{
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println(contextRefreshedEvent);
        System.out.println("TestApplicationListener...");
    }
}
自定义事件
  • 1.定义事件:继承ApplicationEvent
public class NotifyEvent extends ApplicationEvent {
    private String address;
    private String text;
    
    public NotifyEvent(Object source, String address, String text) {
        super(source);
        this.address = address;
        this.text = text;
    }
    public NotifyEvent(Object source) {
        super(source);
    }
   //setter、getter
}
  • 2.定义事件监听器并注册:实现ApplicationListener
@Component
public class NotifyEventListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(NotifyEvent event) {
        if (event instanceof NotifyEvent) {
            System.out.println("邮件地址:" + event.getAddress());
            System.out.println("邮件内容:" + event.getText());
        } else {
            System.out.println("容器本身事件:" + event);
        }
    }
}
  • 3.触发事件,监听器实时监听事件触发,完成业务。
// xml配置
public class SpringTest {
    public static void main(String args[]){
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        //创建一个ApplicationEvent对象
        NotifyEvent event = new NotifyEvent("hello","abc@163.com","This is a test");
        //主动触发该事件
        context.publishEvent(event);
    }
}

// 自动注入
@RunWith(SpringRunner.class)
@SpringBootTest
public class ListenerTest {
	@Autowired
	private WebApplicationContext context;

	@Test
	public void testListener() {
		NotifyEvent event = new NotifyEvent("object", "abc@qq.com", "This is the content");
		context.publishEvent(event);
	}
}
springboot 事件与事件监听器

内置事件:不需手动触发事件,springboot启动后会自动触发事件,实现事件监听中业务。

自定义事件:需手动触发事件,实现事件监听器中业务。

内置事件与执行顺序
顺序事件描述
1ApplicationStartingEvent这个事件在 Spring Boot 应用运行开始时,且进行任何处理之前发送(除了监听器和初始化器注册之外)。
2ApplicationEnvironmentPreparedEvent这个事件在当已知要在上下文中使用 Spring 环境(Environment)时,在 Spring 上下文(context)创建之前发送。
3ApplicationContextInitializedEvent这个事件在当 Spring 应用上下文(ApplicationContext)准备好了,并且应用初始化器(ApplicationContextInitializers)已经被调用,在 bean 的定义(bean definitions)被加载之前发送。
4ApplicationPreparedEvent这个事件是在 Spring 上下文(context)刷新之前,且在 bean 的定义(bean definitions)被加载之后发送。
5ApplicationStartedEvent这个事件是在 Spring 上下文(context)刷新之后,且在 application/ command-line runners 被调用之前发送。
6AvailabilityChangeEvent这个事件紧随上个事件之后发送,状态:ReadinessState.CORRECT,表示应用已处于活动状态。
7ApplicationReadyEvent这个事件在任何 application/ command-line runners 调用之后发送。
8AvailabilityChangeEvent这个事件紧随上个事件之后发送,状态:ReadinessState.ACCEPTING_TRAFFIC,表示应用可以开始准备接收请求了。
9ApplicationFailedEvent这个事件在应用启动异常时进行发送。

可以通过@Order()指定监听器顺序

定义内置事件
  • 自定义内置事件监听器
public class EnvironmentPreparedListener implements ApplicationListener {
    public EnvironmentPreparedListener() {}
    
    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        System.out.println("EnvironmentPreparedListener...");
    }
}
  • 注册事件监听器
@SpringBootApplication
public class MySpringbootApplication {
    public static void main(String[] args) {
//        SpringApplication.run(MySpringbootApplication.class, args);
        SpringApplication sa = new SpringApplication(MySpringbootApplication.class);
        // 添加事件监听
        sa.addListeners(new EnvironmentPreparedListener());
        ConfigurableApplicationContext caContext = sa.run(args);
    }
}
自定义事件

定义事件

public class NotifyEvent extends ApplicationEvent {
    private String address;
    private String text;
    
    public NotifyEvent(Object source, String address, String text) {
        super(source);
        this.address = address;
        this.text = text;
    }
    public NotifyEvent(Object source) {
        super(source);
    }
   //setter、getter
}

定义监听器

public class NotifyEventListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(NotifyEvent event) {
        if (event instanceof NotifyEvent) {
            System.out.println("邮件地址:" + event.getAddress());
            System.out.println("邮件内容:" + event.getText());
        } else {
            System.out.println("容器本身事件:" + event);
        }
    }
}

注册监听器并手动触发事件

@SpringBootApplication
public class MySpringbootApplication {
    public static void main(String[] args) {
//        SpringApplication.run(MySpringbootApplication.class, args);
        SpringApplication sa = new SpringApplication(MySpringbootApplication.class);
        // 手动注册事件器
        sa.addListeners(new NotifyEventListener());
        ApplicationContext context = sa.run(args);
        // 发布事件
        NotifyEvent notifyEvent = new NotifyEvent("nortifyEvent", "localhost", "hello xiaoai");
        context.publishEvent(notifyEvent);
    }
}
事件监听器注册方式
  • 1、@Component + 实现ApplicationListener<>接口
@Component
public class NotifyEventListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(NotifyEvent event) {
        if (event instanceof NotifyEvent) {
            System.out.println("邮件地址:" + event.getAddress());
            System.out.println("邮件内容:" + event.getText());
        } else {
            System.out.println("容器本身事件:" + event);
        }
    }
}
  • 2、@Component + @EventListener
@Component
public class EventListner {
    @EventListener
    public void evendListener(NotifyEvent event){
        if (event instanceof NotifyEvent) {
            System.out.println("邮件地址:" + event.getAddress());
            System.out.println("邮件内容:" + event.getText());
        } else {
            System.out.println("容器本身事件:" + event);
        }
    }
}
  • 3、配置文件注册
context:
  listener:
    classes: com.xiaoai.my_springboot.event.NotifyEventListener
  • 4、启动类手动注册
public static void main(String[] args) {
//        SpringApplication.run(MySpringbootApplication.class, args);
        
    	SpringApplication sa = new SpringApplication(MySpringbootApplication.class);
        // 注册事件监听器器
        sa.addListeners(new NotifyEventListener());
        ApplicationContext context = sa.run(args);
        // 发布事件
        NotifyEvent notifyEvent = new NotifyEvent("nortifyEvent", "localhost", "hello xiaoai");
        notifyEvent.getAddress();
        context.publishEvent(notifyEvent);
    }
  • 5、spring.factories机制注入
# resources目录下新建一个meta-INF 的目录,目录下新建一个spring.factories的文件,里面的内容为:
org.springframework.context.ApplicationListener=com.xiaoai.my_springboot.event.NotifyEventListener
  • 6、多事件监听:@Component + 实现 SmartApplicationListener接口
@Order(1)
@Component
public class SmartListenerTest implements SmartApplicationListener {
    @Override
    public boolean supportsEventType(Class eventType){
        //这里是类型判断,判断监听器感兴趣的事件
        //可以对多个事件感兴趣,这里就配置了两个事件
        return ApplicationStartedEvent.class.isAssignableFrom(eventType)
                || NotifyEvent.class.isAssignableFrom(eventType);
    }

    @Override
    public void onApplicationEvent(ApplicationEvent appEvent) {
        if (appEvent instanceof ApplicationStartedEvent){
            System.out.println("applicationStartedEvent...");
        }
        if (appEvent instanceof NotifyEvent) {
            NotifyEvent event = (NotifyEvent) appEvent;
            System.out.println("邮件地址:" + event.getAddress());
            System.out.println("邮件内容:" + event.getText());
        } else {
            System.out.println("容器本身事件:" + appEvent);
        }
    }
}
自动执行任务 ApplicationRunner
@Component
public class StartTask2 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("-----ApplicationRunner:springboot start......");
    }
}
CommandLineRunner
@Component
public class StartTask implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("-----CommandLineRunner:springboot start......");
    }
}
修饰方法相关注解
  • @PostConstruct

  • @PreDestroy

@Component
public class TestClass {
    // 当bean创建完成加载时执行
    @PostConstruct
    public String init(){
        System.out.println("-----@PostConstruct:TestClass method 【init】 is run.....");
        return "hello";
    }

    // 关闭前执行
    @PreDestroy
    public void destroyPro(){
        System.out.println("-----@PreDestroy:TestClass method 【destroyPro】 is run.....");
    }
}
BeanPostProcessor

运行顺序:

  • Spring IOC容器实例化Bean
  • 调用BeanPostProcessor的postProcessBeforeInitialization方法
  • 调用bean实例的初始化方法
  • 调用BeanPostProcessor的postProcessAfterInitialization方法
@Component
public class StartTask3 implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // 可以根据不同的bean执行不同的操作
        if (beanName.equalsIgnoreCase("eventListner")){
            System.out.println("postProcessBeforeInitialization()..." + beanName + "=>" + bean);
            System.out.println("eventListner is loading...");
        }
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equalsIgnoreCase("eventListner")){
            System.out.println("postProcessAfterInitialization()..." + beanName + "=>" + bean);
            System.out.println("eventListner is loaded...");
        }
        return null;
    }
}
BeanFactoryPostProcessor
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanFactoryPostProcessor...postProcessBeanFactory...");
        int count = beanFactory.getBeanDefinitionCount();
        String[] names = beanFactory.getBeanDefinitionNames();
        System.out.println("当前BeanFactory中有【" + count + "】个Bean");
//        System.out.println(Arrays.asList(names));
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/439423.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号