《Spring揭 秘》重置版06——容器内部事件发布

9 篇文章 0 订阅

27岁能干嘛,当然是继续学习。学海无涯,一叶扁舟,随便游。

java自定义事件发布

逻辑

了解ApplicationContext容器内部事件发布之前,我们先来了解一下java的自定义事件发布。本例大概如图所示

在这里插入图片描述

一,定义一个事件MethodExecutionEvent(继承EventObject

二,定义一个监听器SimpleMethodExcutionEventListener,设置onMethodBeginonMethodEnd在事件开始前后监听事件。

三,定义一个类MethodExcutionEventPublisher发布事件,及在不同的时机注册、调用、移除监听器。

代码实例

具体代码,如下:

package event;

import java.util.EventObject;

//自定义事件类型:MethodExecutionEvent
public class MethodExecutionEvent extends EventObject {
    private static final long serialVersionUID = 1L;
    private String methodName;

    public MethodExecutionEvent(Object source) {
        super(source);
    }
    public MethodExecutionEvent(Object source,String methodName) {
        super(source);
        this.methodName = methodName;
    }
    public String getMethodName() {
        return methodName;
    }
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }
}

package event;

import java.util.EventListener;

//自定义MethodExecutionEvent的事件监听器接口
public interface MethodExcutionEventListener extends EventListener {
    /**
     * 处理方法开始执行的时候发布的MethodExecutionEvent事件
     * @param evt
     */
    void onMethodBegin(MethodExecutionEvent evt);

    /**
     * 处理方法执行结束时发布的MethodExecutionEvent事件
     * @param evt
     */
    void onMethodEnd(MethodExecutionEvent evt);
}
package event;

//实现监听器
public class SimpleMethodExcutionEventListener implements MethodExcutionEventListener{
    public void onMethodBegin(MethodExecutionEvent evt) {
        String methodName = evt.getMethodName();
        System.out.println("start to execute the method["+methodName+"].");
    }

    public void onMethodEnd(MethodExecutionEvent evt) {
        String methodName = evt.getMethodName();
        System.out.println("finished to execute the method["+methodName+"].");
    }
}
package event;

public enum MethodExecutionStatus {
    BEGIN("1"),END("2");
    private String name;
    private MethodExecutionStatus(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

import java.util.ArrayList;
import java.util.List;
//发布事件
public class MethodExcutionEventPublisher {
    //事件监听器列表
    private List<MethodExcutionEventListener> listeners = new
            ArrayList<MethodExcutionEventListener>();

    public void methodToMonitor() {
        MethodExecutionEvent event2Publish =
        new MethodExecutionEvent(this,"methodToMonitor");
        publishEvent(MethodExecutionStatus.BEGIN,event2Publish);
        //....事件具体执行
        publishEvent(MethodExecutionStatus.END,event2Publish);
    }
    protected void publishEvent(MethodExecutionStatus status,
                                MethodExecutionEvent methodExecutionEvent) {
        //为了避免事件处理期间,监听器列表发生变化,所以复制一个当前节点的监听器列表。
        List<MethodExcutionEventListener> copyListeners =
                new ArrayList<MethodExcutionEventListener>(listeners);
        for (MethodExcutionEventListener listener:copyListeners) {
            if (MethodExecutionStatus.BEGIN.equals(status)) {
                listener.onMethodBegin(methodExecutionEvent);
            } else {
                listener.onMethodEnd(methodExecutionEvent);
            }
        }
    }

    //增加事件监听器
    public void addMethodExecutionEventListener(MethodExcutionEventListener listener) {
        this.listeners.add(listener);
    }
    //移除事件监听器
    public void removeListener(MethodExcutionEventListener listener) {
        if (this.listeners.contains(listener)) {
            this.listeners.remove(listener);
        }
    }
    //移除所有事件监听器
    public void removeAllListeners() {
        this.listeners.clear();
    }
    public static void main(String[] args) {
        MethodExcutionEventPublisher eventPublisher =
                new MethodExcutionEventPublisher();
        eventPublisher.addMethodExecutionEventListener(new
                SimpleMethodExcutionEventListener());
        eventPublisher.methodToMonitor();
    }
}

ApplicationContext容器内部事件发布

逻辑

它的发布所用类和前面类似,主要是ApplicationEvent、ApplicationListener、ApplicationContext(继承了发布方法,但主要作用是调用其他的类来发布)

下面以以一个实例来了解他们。

执行过程是这样的,

第一,将MethodExcutionEventPublisher需要的属性ApplicationEventPublisher注册到xml文件

第二,将自定义的listener——MethodExcutionEventListener注册到xml文件内

第三,将xml文件加载到spring的ApplicationContext容器中。

这里有一点需要注意。
为啥执行了  this.eventPublisher.publishEvent(endEvt); 就可以调用MethodExcutionEventListener了呢?

因为我们将监听器注入到了容器中。
然后AbstractApplicationContext调用了ApplicationEventMulticaster去装载监听器。

在这里插入图片描述

第四,创建事件

第五,发布事件

代码实例

package applicationEvent;

import org.springframework.context.ApplicationEvent;

import java.util.EventObject;

//自定义事件类型:MethodExecutionEvent
public class MethodExecutionEvent extends ApplicationEvent {
    private static final long serialVersionUID = 1L;
    private String methodName;
    private MethodExecutionStatus methodExecutionStatus;
    public MethodExecutionEvent(Object source) {
        super(source);
    }
    public MethodExecutionEvent(Object source,String methodName,
    MethodExecutionStatus methodExecutionStatus) {
        super(source);
        this.methodName = methodName;
        this.methodExecutionStatus = methodExecutionStatus;
    }
    public String getMethodName() {
        return methodName;
    }
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public MethodExecutionStatus getMethodExecutionStatus() {
        return methodExecutionStatus;
    }

    public void setMethodExecutionStatus(MethodExecutionStatus methodExecutionStatus) {
        this.methodExecutionStatus = methodExecutionStatus;
    }
}

package applicationEvent;

public enum MethodExecutionStatus {
    BEGIN("1"),END("2");
    private String name;
    private MethodExecutionStatus(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

package applicationEvent;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;

import java.util.EventListener;

//自定义MethodExecutionEvent的事件监听器接口
public class MethodExcutionEventListener implements ApplicationListener {

    @Override
    public void onApplicationEvent(ApplicationEvent evt) {
        if (evt instanceof  MethodExecutionEvent) {
            String methodName = ((MethodExecutionEvent) evt).getMethodName();
            System.out.println("execute the method["+methodName+"].");
        }
    }
}

package applicationEvent;

import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.List;

//发布事件
public class MethodExcutionEventPublisher implements ApplicationEventPublisherAware {
    private ApplicationEventPublisher eventPublisher;

    public void methodToMonitor() {
        //创建事件
        MethodExecutionEvent beginEvt =
        new MethodExecutionEvent(this,"methodToMonitor",
                MethodExecutionStatus.BEGIN);
        //发布事件
        this.eventPublisher.publishEvent(beginEvt);
        //....事件具体执行
        MethodExecutionEvent endEvt =
                new MethodExecutionEvent(this,"methodToMonitor",
                        MethodExecutionStatus.END);
        this.eventPublisher.publishEvent(endEvt);
    }

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

    public static void main(String[] args) {
        //创建Spring的ioc容器,读取配置文件的beans.xml
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        MethodExcutionEventPublisher evtPublisher = context.getBean(MethodExcutionEventPublisher.class);
        evtPublisher.methodToMonitor();
    }
}

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE beans PUBLIC
        "-//SPRING//DTD BEAN//EN"
        "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="methodExecListener" class="applicationEvent.MethodExcutionEventListener"></bean>
    <bean id="evtPublisher" class="applicationEvent.MethodExcutionEventPublisher"></bean>
</beans>

代码链接

java自定义事件发布
ApplicationContext容器内部事件发布

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨_浅-

你的一毛/分钱是我最大的鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值