Java Spring 自定义事件监听

Posted 每周向前一小步

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Spring 自定义事件监听相关的知识,希望对你有一定的参考价值。

 

ApplicationContext 事件

定义一个context的起动监听事件

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStartedEvent;

public class EventStart implements ApplicationListener<ContextStartedEvent>{

    @Override
    public void onApplicationEvent(ContextStartedEvent arg0) {
        System.out.println("上下文 开始 事件");
    }
}
要定义一个事件监听,首先你得有一个事件,ContextStartedEvent 是一个固定的、具体的事件,Java spring自带的,通过实现
ApplicationListener<ContextStartedEvent >
就可以监控这个事件了
ContextStartedEvent 的定义 
@SuppressWarnings("serial")
public class ContextStartedEvent extends ApplicationContextEvent {

    /**
     * Create a new ContextStartedEvent.
     * @param source the {@code ApplicationContext} that has been started
     * (must not be {@code null})
     */
    public ContextStartedEvent(ApplicationContext source) {
        super(source);
    }

}

 

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStoppedEvent;

public class EventStop implements ApplicationListener<ContextStoppedEvent> {

    @Override
    public void onApplicationEvent(ContextStoppedEvent arg0) {
        System.out.println("上下文 停止 事件");
    }
}

 

主方法

        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("b.xml");
        context.start();
        
        Dept dept = (Dept)context.getBean("dept");
        dept.getLeader();
        
        context.stop();
        context.registerShutdownHook();

b.xml

<bean id="eventStart" class="test4.EventStart"></bean>
<bean id="eventStop" class="test4.EventStop"></bean>

 

输出

初始化 bean.洪七公
初始化 bean.null
家
我
上下文 开始 事件
部门领导洪七公
上下文 停止 事件
销毁 bean.null
销毁 bean.洪七公

为什么主方法中一调用 start 方法,监听事件就可以自己被调用 呢

 

start方法真正执行的是AbstractApplicationContext的start方法,在方法里,除子真正start要处理的内容外,还额外加了事件处理,

@Override
    public void start() {
        getLifecycleProcessor().start();
        publishEvent(new ContextStartedEvent(this));
    }

所加的事件就是ContextStartedEvent事件,在将实例了ApplicationListener<ContextStartedEvent>的bean通过xml注册到spring容器中时,容器自动调用了该bean的onApplicationEvent方法

 

 自定义事件

public class Person {
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

public class Work extends ApplicationEvent{
    private static final long serialVersionUID = 1L;
    private Person ps;

    public void setPs(Person ps) {
        this.ps = ps;
    }

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

    public void doWorking() {
        String name = this.ps.getName();
        System.out.println(name + " 今天没有完成100张图片制作,并且听到这个任务时,情绪时而激动,时而低落");
    }
}
//该类要注册到spring容器,然后容器会自动调用实现ApplicationListener接口的类的onApplicationEvent方法
public class WorkListener implements ApplicationListener<Work>{

    @Override
    public void onApplicationEvent(Work event) {
        // TODO Auto-generated method stub
        System.out.println("摄像头记录到:");
        event.doWorking();
    }
}
public class Sleep extends ApplicationEvent{

    private Person ps;
    public void setPs(Person ps) {
        this.ps = ps;
    }

    private static final long serialVersionUID = 2L;
    public Sleep(Object source) {
        super(source);
    }
    
    public void doSleeping() {
        String name = this.ps.getName();
        System.out.println(name + " 开始休息了");
    }
}
//该类要注册到spring容器,然后容器会自动调用实现ApplicationListener接口的类的onApplicationEvent方法
public class SleepListener implements ApplicationListener<Sleep> {

    @Override
    public void onApplicationEvent(Sleep event) {
        System.out.println("摄像头记录到:");
        event.doSleeping();
    }
}
public class Report implements ApplicationEventPublisherAware{
    private ApplicationEventPublisher publisher;
    
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
    
    public void work() {
        System.out.println("开始小明的工作报告");
        Work work = new Work(this);
        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("d.xml");
        Person xm = (Person)context.getBean("xiaoming");
        work.setPs(xm);
        this.publisher.publishEvent(work);
    }
    
    public void sleep() {
        System.out.println("开始小明的睡眠报告");
        Sleep sl = new Sleep(this);
        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("d.xml");
        Person xm = (Person)context.getBean("xiaoming");
        sl.setPs(xm);
        this.publisher.publishEvent(sl);
    }
}
    <bean name="xiaoming" class="test6.Person">
        <property name="name" value="小明"></property>
    </bean>
    
    <bean id="wkReport" class="test6.Report"></bean>
    <bean id="wkMonitor" class="test6.WorkListener"></bean>
    <bean id="slMonitor" class="test6.SleepListener"></bean>
public class Main {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("d.xml");
        Report rp = (Report)context.getBean("wkReport");
        rp.work();
        rp.sleep();
        context.close();
    }
}

输出

开始小明的工作报告
摄像头记录到:
小明 今天没有完成100张图片制作,并且听到这个任务时,情绪时而激动,时而低落
开始小明的睡眠报告
摄像头记录到:
小明 开始休息了

事件本身,Work,Sleep不需要注册到sping容器中。

想要让

rp.work();rp.sleep();
工作,睡觉这样的方法/行为,可以被监控,除了这些方法本身要处理的内容外,
还需要为这个方法定义一个具体的事件类(此例中是Work,Sleep,这些具体的事件类不需要注册到spring容器,因为他们在工作、睡觉这些方法中已经被调用了),
然后将对应的事件类添加到
ApplicationEventPublisher事件处理的逻辑中;
在我们调用 工作、睡觉这些方法时,就会触发事件处理逻辑,
spring容器会自动检测哪些bean实现了与之相对应的ApplicationListener监听类,然后调用其onApplicationEvent方法

以上是关于Java Spring 自定义事件监听的主要内容,如果未能解决你的问题,请参考以下文章

spring 自定义事件发布及监听(简单实例)

Spring标准事件和自定义事件-观察者模式

Spring标准事件和自定义事件-观察者模式

Spring标准事件和自定义事件-观察者模式

Spring标准事件和自定义事件-观察者模式

java 自定义事件的触发及监听