码迷,mamicode.com
首页 > 编程语言 > 详细

009-Spring Boot 事件监听

时间:2018-01-25 00:15:42      阅读:420      评论:0      收藏:0      [点我收藏+]

标签:either   图片   tin   1.5   red   play   stop   ext.get   post   

一、概念

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等

 

009-Spring Boot 事件监听

标签:either   图片   tin   1.5   red   play   stop   ext.get   post   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!