009-Spring Boot 事件监听

一、概念

1.事件监听的流程

  步骤一、自定义事件,一般是继承ApplicationEvent抽象类

  步骤二、定义事件监听器,一般是实现ApplicationListener接口

  步骤三、启动时,需要将监听器加入到Spring容器中

  步骤四、发布事件

对于配置监听器的方式【即第三步】

  方式一、app.addListeners(new MyApplicationListener());添加监听器

  方式二、把监听器使用纳入Spring配置中管理如使用@Component标注

  方式三、再application.properties中添加context.listener.classes配置项配置

  方式四、使用注解@EventListener在方法上,且该类需要在Spring上管理

2、示例【方式一】:

步骤一、自定义事件MyApplicationEvent

package com.lhx.spring.springboot_event;

import org.springframework.context.ApplicationEvent;

/**
 * 定义事件
 * @author Administrator
 *
 */
public class MyApplicationEvent extends ApplicationEvent {
    private static final long serialVersionUID = 1L;

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

步骤二、定义事件监听器MyApplicationListener

package com.lhx.spring.springboot_event;

import org.springframework.context.ApplicationListener;

public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {

    @Override
    public void onApplicationEvent(MyApplicationEvent event) {
        System.out.println("接收到事件:" + event.getClass());
    }

}

步骤三、在App启动程序中添加以及发布

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        // ConfigurableApplicationContext context = SpringApplication.run(App.class,
        // args);
        SpringApplication app = new SpringApplication(App.class);
        app.addListeners(new MyApplicationListener());
        ConfigurableApplicationContext context = app.run(args);
        context.publishEvent(new MyApplicationEvent(new Object()));
        context.close();
    }
}

3、示例【方式二】:

注意:其实在示例步骤三,也可以用注解方式将时间监听器纳入Spring管理中

步骤一、与示例一一致

步骤二、将事件监听器添加@Component注解。

步骤三、启动类

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(App.class);
        //app.addListeners(new MyApplicationListener());
        ConfigurableApplicationContext context = app.run(args);
        context.publishEvent(new MyApplicationEvent(new Object()));
        context.close();
    }
}

4、示例【方式四】:

步骤一、与示例一一致

步骤二、与示例一一致

步骤三、增加单独处理类

package com.lhx.spring.springboot_event;

import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyEventHandle {
    @EventListener
    public void event(MyApplicationEvent event) {
        System.out.println("MyEventHandle 接收到事件:" + event.getClass());
    }

    @EventListener
    public void event2(ContextStoppedEvent event) {
        System.out.println("应用停止  接收到事件:" + event.getClass());
    }
}

步骤三、启动类

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(App.class);、
        ConfigurableApplicationContext context = app.run(args);
        context.publishEvent(new MyApplicationEvent(new Object()));
        context.close();
    }
}

二、配置监听器的方式原理

1.方式三实现,在application.properties中添加context.listener.classes配置项配置

查看:DelegatingApplicationListener

public class DelegatingApplicationListener
        implements ApplicationListener<ApplicationEvent>, Ordered {

    // NOTE: Similar to org.springframework.web.context.ContextLoader

    private static final String PROPERTY_NAME = "context.listener.classes";

核心逻辑

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ApplicationEnvironmentPreparedEvent) {
            List<ApplicationListener<ApplicationEvent>> delegates = getListeners(
                    ((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
            if (delegates.isEmpty()) {
                return;
            }
            this.multicaster = new SimpleApplicationEventMulticaster();
            for (ApplicationListener<ApplicationEvent> listener : delegates) {
                this.multicaster.addApplicationListener(listener);
            }
        }
        if (this.multicaster != null) {
            this.multicaster.multicastEvent(event);
        }
    }

    @SuppressWarnings("unchecked")
    private List<ApplicationListener<ApplicationEvent>> getListeners(
            ConfigurableEnvironment environment) {
        if (environment == null) {
            return Collections.emptyList();
        }
        String classNames = environment.getProperty(PROPERTY_NAME);
        List<ApplicationListener<ApplicationEvent>> listeners = new ArrayList<ApplicationListener<ApplicationEvent>>();
        if (StringUtils.hasLength(classNames)) {
            for (String className : StringUtils.commaDelimitedListToSet(classNames)) {
                try {
                    Class<?> clazz = ClassUtils.forName(className,
                            ClassUtils.getDefaultClassLoader());
                    Assert.isAssignable(ApplicationListener.class, clazz, "class ["
                            + className + "] must implement ApplicationListener");
                    listeners.add((ApplicationListener<ApplicationEvent>) BeanUtils
                            .instantiateClass(clazz));
                }
                catch (Exception ex) {
                    throw new ApplicationContextException(
                            "Failed to load context listener class [" + className + "]",
                            ex);
                }
            }
        }
        AnnotationAwareOrderComparator.sort(listeners);
        return listeners;
    }

2、方式四实现

查看:EventListenerMethodProcessor的processBean

    protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {
        if (!this.nonAnnotatedClasses.contains(targetType)) {
            Map<Method, EventListener> annotatedMethods = null;
            try {
                annotatedMethods = MethodIntrospector.selectMethods(targetType,
                        new MethodIntrospector.MetadataLookup<EventListener>() {
                            @Override
                            public EventListener inspect(Method method) {
                                return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
                            }
                        });
            }
            catch (Throwable ex) {
                // An unresolvable type in a method signature, probably from a lazy bean - let‘s ignore it.
                if (logger.isDebugEnabled()) {
                    logger.debug("Could not resolve methods for bean with name ‘" + beanName + "‘", ex);
                }
            }
            if (CollectionUtils.isEmpty(annotatedMethods)) {
                this.nonAnnotatedClasses.add(targetType);
                if (logger.isTraceEnabled()) {
                    logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
                }
            }
            else {
                // Non-empty set of methods
                for (Method method : annotatedMethods.keySet()) {
                    for (EventListenerFactory factory : factories) {
                        if (factory.supportsMethod(method)) {
                            Method methodToUse = AopUtils.selectInvocableMethod(
                                    method, this.applicationContext.getType(beanName));
                            ApplicationListener<?> applicationListener =
                                    factory.createApplicationListener(beanName, targetType, methodToUse);
                            if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                                ((ApplicationListenerMethodAdapter) applicationListener)
                                        .init(this.applicationContext, this.evaluator);
                            }
                            this.applicationContext.addApplicationListener(applicationListener);
                            break;
                        }
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean ‘" +
                            beanName + "‘: " + annotatedMethods);
                }
            }
        }
    }

EventListener

                annotatedMethods = MethodIntrospector.selectMethods(targetType,
                        new MethodIntrospector.MetadataLookup<EventListener>() {
                            @Override
                            public EventListener inspect(Method method) {
                                return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);
                            }
                        });

查看for

                for (Method method : annotatedMethods.keySet()) {
                    for (EventListenerFactory factory : factories) {
                        if (factory.supportsMethod(method)) {
                            Method methodToUse = AopUtils.selectInvocableMethod(
                                    method, this.applicationContext.getType(beanName));
                            ApplicationListener<?> applicationListener =
                                    factory.createApplicationListener(beanName, targetType, methodToUse);
                            if (applicationListener instanceof ApplicationListenerMethodAdapter) {
                                ((ApplicationListenerMethodAdapter) applicationListener)
                                        .init(this.applicationContext, this.evaluator);
                            }
                            this.applicationContext.addApplicationListener(applicationListener);
                            break;
                        }
                    }
                }

其中factory即EventListenerFactory factory

/*
 * Copyright 2002-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.event;

import java.lang.reflect.Method;

import org.springframework.context.ApplicationListener;

/**
 * Strategy interface for creating {@link ApplicationListener} for methods
 * annotated with {@link EventListener}.
 *
 * @author Stephane Nicoll
 * @since 4.2
 */
public interface EventListenerFactory {

    /**
     * Specify if this factory supports the specified {@link Method}.
     * @param method an {@link EventListener} annotated method
     * @return {@code true} if this factory supports the specified method
     */
    boolean supportsMethod(Method method);

    /**
     * Create an {@link ApplicationListener} for the specified method.
     * @param beanName the name of the bean
     * @param type the target type of the instance
     * @param method the {@link EventListener} annotated method
     * @return an application listener, suitable to invoke the specified method
     */
    ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method);

}

三、spring、Spring boot内置事件

1.Spring

jar包:Spring-context-4.3.13.RELEASE

  包:org.springframwork.context.event;

常用:ContextClosedEvent、ContextStartedEvent、ContextStopedEvent

示例

@Component
public class MyEventHandle {
    @EventListener
    public void event2(ContextStoppedEvent event) {
        System.out.println("应用停止  接收到事件:" + event.getClass());
    }
}

当然:app中Context要停止

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(App.class);
        ConfigurableApplicationContext context = app.run(args);
        context.publishEvent(new MyApplicationEvent(new Object()));
        context.stop();
    }
}

2.Spring-boot

jar包:Spring-boot-1.5.9.RELEASE

  包:org.springframework.boot.context.event;

常用:ApplicationEnvironmentPreparedEvent、ApplicationFailedEvent等

原文地址:https://www.cnblogs.com/bjlhx/p/8343855.html

时间: 2024-08-11 01:19:56

009-Spring Boot 事件监听的相关文章

十一、Spring之事件监听

Spring之事件监听 ApplicationListener ApplicationListener是Spring事件机制的一部分,与抽象类ApplicationEvent类配合来完成ApplicationContext的事件机制. 如果容器中存在ApplicationListener的Bean,当ApplicationContext调用publishEvent方法时,对应的Bean会被触发.这一过程是典型的观察者模式的实现. 源码: @FunctionalInterface public i

Java Spring 自定义事件监听

ApplicationContext 事件 定义一个context的起动监听事件 import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextStartedEvent; public class EventStart implements ApplicationListener<ContextStartedEvent>{ @Override pub

spring boot 学习 ---- 使用事件监听

spring 的事件监听 事件监听其实我们并不陌生,简单来讲,当程序达到了某个特定的条件,程序就会自动执行一段指令.在spring 中也一样,我们可以使用spring中的事件监听来实现某些特定的需求. 发布事件 既然要监听事件,首先要发布我们的事件嘛.在spring中发布事件我们可以通过继承ApplicationEvent 来发布我们的事件类. @Data public class SendEvent extends ApplicationEvent { public SendEvent(Obj

java 事件监听

事件监听实现: 三要素: 1.事件源(数据源,要处理的数据) 2.事件 (承载数据,传递信息并被监听) 3.监听器 (负责对数据的业务处理) --该开发用例采用了Spring的事件监听 1.  定义事件类型 public class MyEvent extends ApplicationEvent { private static final long serialVersionUID = 7937618461275424515L; // 其他属性 (非必须) ... ... public My

spring boot 源码赏析之事件监听

使用spring Boot已经快1年多了,期间一直想点开springboot源码查看,但由于种种原因一直未能如愿(主要是人类的惰性...),今天就拿springboot 的监听事件祭刀. springboot 中常用的事件监听主要有ApplicationStartedEvent,ApplicationEnviromentPreparedEvent,ApplicationPreparedEvent,ApplicationStoppedEvent等.用于监听springboot生命周期中的各种事件.

Spring Boot实践——事件监听

借鉴:https://blog.csdn.net/Harry_ZH_Wang/article/details/79691994 https://blog.csdn.net/ignorewho/article/details/80702827     https://www.jianshu.com/p/edd4cb960da7 事件监听介绍 Spring提供5种标准的事件监听: 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者

Spring架构揭秘-事件监听机制

一.事件监听机制概述 二.事件监听机制结构 三.Spring监听机制架构 Spring的Application拥有发布事件并且注册事件监听器的能力,拥有一套完整的事件发布和监听机制.在Java中,通过java.util. EventObject来描述事件,通过java.util. EventListener来描述事件监听器,在众多的框架和组件中,建立一套事件机制通常是基于这两个接口来进行扩展. 在一个事件体系中,有以下几个重要的概念. 1.事件源:事件对象的产生者,任何一个EventObject

SpringBoot入门之事件监听

spring boot在启动过程中增加事件监听机制,为用户功能拓展提供极大的便利,sptingboot支持的事件类型有以下五种: ApplicationStartingEvent ApplicationFailedEvent ApplicationPreparedEvent ApplicationReadyEvent ApplicationEnvironmentPreparedEvent 实现监听步骤 1.监听类实现ApplicationListener接口 2.将监听类添加到SpringApp

Springboot-Listener(springboot的事件监听的4种实现方式)

springboot事件监听的4种方式 第1种: 1.自定义事件MyApplicationEvent继承ApplicationEvent import org.springframework.context.ApplicationEvent; /** * Created by Administrator on 2018\11\13 0013. * 自定义事件继承ApplicationEvent */public class MyApplicationEvent extends Applicati