Java事件监听器原理以及使用Spring的事件监听

事件监听包括必不可少的三个元素:事件、事件源和监听器。

事件:容易理解,点击一下鼠标是一个事件,更改某个类属性也可以抽象为一个事件。

事件源:发布事件的地方,也就是事件产生的地方。

监听器:定义事件发生后要采取的操作。

1,接下来举例说明Java如何实现监听模式

事件:

package com.wxy.popcorn.eventlistener.model;

import java.util.EventObject;

public class MyEvent extends EventObject {
    private String name;

    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public MyEvent(Object source, String name) {
        super(source);
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

事件源:

package com.wxy.popcorn.eventlistener.model;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import com.wxy.popcorn.eventlistener.listener.MyListener;

public class EventSource {
    private String name;
    private Set<MyListener> listeners = new HashSet<MyListener>();

    public void addListener(MyListener myListener) {
        listeners.add(myListener);
    }

    public void removeListener(MyListener myListener) {
        listeners.remove(myListener);
    }

    public void notifyEvent(MyEvent myEvent) {
        Iterator<MyListener> iterator = listeners.iterator();
        while(iterator.hasNext()) {
            MyListener listener = iterator.next();
            listener.handleEvent(myEvent);
        }
    }

    //当name属性发生了改变时发布一个事件。当然,完全可以在其他的逻辑下发布事件
    public void updateName(String name) {
        if(name==null && this.name==null) {
            return;
        }
        if (name==null || this.name==null || !name.equals(this.name)) {
            this.name = name;
            notifyEvent(new MyEvent(this, name));
        }
    }
}


监听器接口:

package com.wxy.popcorn.eventlistener.listener;

import java.util.EventListener;

import com.wxy.popcorn.eventlistener.model.MyEvent;

public interface MyListener extends EventListener{
    void handleEvent(MyEvent myEvent);
}


监听器实现:

package com.wxy.popcorn.eventlistener.listener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wxy.popcorn.eventlistener.model.MyEvent;

public class MyListenerImpl implements MyListener{
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    public void handleEvent(MyEvent myEvent) {
        logger.info("the name was set to {}", myEvent.getName());
    }
}


测试类:

package com.wxy.popcorn;

import org.junit.Test;

import com.wxy.popcorn.eventlistener.listener.MyListenerImpl;
import com.wxy.popcorn.eventlistener.model.EventSource;

public class EventlistenerTest {

    @Test
    public void test() {
        EventSource eventSource = new EventSource();
        eventSource.addListener(new MyListenerImpl());
        eventSource.updateName("popcorn");
    }
}

运行结果:

2018-01-07 19:01:36.886 [main] INFO  [MyListenerImpl.java:11] the name was set to popcorn

2,Spring事件监听

事件:继承于SpringEvent,当然也可以不从SpringEvent继承,任意Object都可以作为事件发布。

事件源:事件源必须实现 ApplicationEventPublisherAware 接口,调用ApplicationEventPublisher.publishEvent()发布事件。

监听:使用@EventListener注解来标注事件处理方法,方法参数是事件对象。如果需要异步监听,则增加@Async注解。

事件类:

package com.wxy.popcorn.eventlistener.model;

import org.springframework.context.ApplicationEvent;

public class SpringEvent extends ApplicationEvent {

    private String name;

    public SpringEvent(Object source, String name) {
        super(source);
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

事件源:

package com.wxy.popcorn.eventlistener.model;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;

@Service
public class SpringEventSource implements ApplicationEventPublisherAware {
    private String name;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    public void updateName(String name) {
        if(name==null && this.name==null) {
            return;
        }
        if (name==null || this.name==null || !name.equals(this.name)) {
            this.name = name;
            applicationEventPublisher.publishEvent(new SpringEvent(this, name));
        }
    }
}

监听器:

package com.wxy.popcorn.eventlistener.listener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.wxy.popcorn.eventlistener.model.SpringEvent;

@Service
public class SpringListener {
    Logger logger = LoggerFactory.getLogger(this.getClass());

    @EventListener
    @Async //异步监听
    public void handleEvent(SpringEvent springEvent) {
        logger.info("the name was set to {}", springEvent.getName());
    }
}

测试类:

package com.wxy.popcorn;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.wxy.popcorn.eventlistener.App;
import com.wxy.popcorn.eventlistener.model.SpringEventSource;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class SpringEventlistenerTest {

    @Autowired
    SpringEventSource springEventSource;

    @Test
    public void test() {
        springEventSource.updateName("popcorn");
    }
}


测试结果:

2018-01-07 19:11:37.479 [main] INFO  [SpringListener.java:18] the name was set to popcorn



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值