zoukankan      html  css  js  c++  java
  • 009-Spring Boot 事件监听、监听器配置与方式、spring、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);
        }
    }
    View Code

    步骤二、定义事件监听器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());
        }
    
    }
    View Code

    步骤三、在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());
        }
    }
    View Code

    步骤三、启动类

    @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();
        }
    }
    View Code

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

    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;
        }
    View Code

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

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

    三、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等

  • 相关阅读:
    VC环境OpenSSL编译笔记
    手动造工具TaskJobManage
    Java性能分析工具
    ES77
    Flink消费kafka
    阻塞对列
    C# 超时事件
    毕业前做一件事
    PID控制器——控制网络爬虫速度
    2.5 OpenEuler 中C与汇编的混合编程(选做)
  • 原文地址:https://www.cnblogs.com/bjlhx/p/8343855.html
Copyright © 2011-2022 走看看