Spring手撸源码系列-容器事件和事件监听器

Spring中有个event事件,可以提供事件的定义、监听和发布事件操作,此次事件监听发布的实现采用的是观察者模式,这种一个地方发布了事件,需要另一个地方立刻监听感知到比较适合观察者模式,实现完毕,我们自定义实现的事件可以在spring生命周期里进行定义,监听发布。

在此种实现中,需要设计出事件定义,对事件的监听,以及对事件的发布,对事件的发布需要广播器进行处理等等,程序的入口,需要用到之前都一直在用的上下文刷新类AbstractApplicationContext的refresh(),用它初始化事件广播器,并发布一些刷新事件和关闭容器等事件,接下来咱们开始把

1.工程目录

├─src
│  ├─main
│  │  ├─java
│  │  │  └─com
│  │  │      └─spring
│  │  │          └─sourcecode
│  │  │              │  SourcecodeApplication.java
│  │  │              │  
│  │  │              └─springframework
│  │  │                  │  BeanDefinition.java
│  │  │                  │  BeanFactory.java
│  │  │                  │  
│  │  │                  ├─beans
│  │  │                  │  │  BeansException.java
│  │  │                  │  │  PropertyValue.java
│  │  │                  │  │  PropertyValues.java
│  │  │                  │  │  
│  │  │                  │  └─factory
│  │  │                  │      │  Aware.java
│  │  │                  │      │  BeanClassLoaderAware.java
│  │  │                  │      │  BeanFactory.java
│  │  │                  │      │  BeanFactoryAware.java
│  │  │                  │      │  BeanNameAware.java
│  │  │                  │      │  ConfigurableListableBeanFactory.java
│  │  │                  │      │  DisposableBean.java
│  │  │                  │      │  FactoryBean.java
│  │  │                  │      │  HierarchicalBeanFactory.java
│  │  │                  │      │  InitializingBean.java
│  │  │                  │      │  ListableBeanFactory.java
│  │  │                  │      │  
│  │  │                  │      ├─config
│  │  │                  │      │      AutowireCapableBeanFactory.java
│  │  │                  │      │      BeanDefinition.java
│  │  │                  │      │      BeanFactoryPostProcessor.java
│  │  │                  │      │      BeanPostProcessor.java
│  │  │                  │      │      BeanReference.java
│  │  │                  │      │      ConfigurableBeanFactory.java
│  │  │                  │      │      SingletonBeanRegistry.java
│  │  │                  │      │      
│  │  │                  │      ├─support
│  │  │                  │      │      AbstractAutowireCapableBeanFactory.java
│  │  │                  │      │      AbstractBeanDefinitionReader.java
│  │  │                  │      │      AbstractBeanFactory.java
│  │  │                  │      │      BeanDefinitionReader.java
│  │  │                  │      │      BeanDefinitionRegistry.java
│  │  │                  │      │      CglibSubclassingInstantiationStrategy.java
│  │  │                  │      │      DefaultListableBeanFactory.java
│  │  │                  │      │      DefaultSingletonBeanRegistry.java
│  │  │                  │      │      DisposableBeanAdapter.java
│  │  │                  │      │      FactoryBeanRegistrySupport.java
│  │  │                  │      │      InstantiationStrategy.java
│  │  │                  │      │      SimpleInstantiationStrategy.java
│  │  │                  │      │      
│  │  │                  │      └─xml
│  │  │                  │              XmlBeanDefinitionReader.java
│  │  │                  │              
│  │  │                  ├─context
│  │  │                  │  │  ApplicationContext.java
│  │  │                  │  │  ApplicationContextAware.java
│  │  │                  │  │  ApplicationEvent.java
│  │  │                  │  │  ApplicationEventPublisher.java
│  │  │                  │  │  ApplicationListener.java
│  │  │                  │  │  ConfigurableApplicationContext.java
│  │  │                  │  │  
│  │  │                  │  ├─event
│  │  │                  │  │      AbstractApplicationEventMulticaster.java
│  │  │                  │  │      ApplicationContextEvent.java
│  │  │                  │  │      ApplicationEventMulticaster.java
│  │  │                  │  │      ContextClosedEvent.java
│  │  │                  │  │      ContextRefreshedEvent.java
│  │  │                  │  │      SimpleApplicationEventMulticaster.java
│  │  │                  │  │      
│  │  │                  │  └─supprot
│  │  │                  │          AbstractApplicationContext.java
│  │  │                  │          AbstractRefreshableApplicationContext.java
│  │  │                  │          AbstractXmlApplicationContext.java
│  │  │                  │          ApplicationContextAwareProcessor.java
│  │  │                  │          ClassPathXmlApplicationContext.java
│  │  │                  │          
│  │  │                  ├─core
│  │  │                  │  └─io
│  │  │                  │          ClassPathResource.java
│  │  │                  │          DefaultResourceLoader.java
│  │  │                  │          FileSystemResource.java
│  │  │                  │          Resource.java
│  │  │                  │          ResourceLoader.java
│  │  │                  │          UrlResource.java
│  │  │                  │          
│  │  │                  └─util
│  │  │                          ClassUtils.java
│  │  │                          
│  │  └─resources
│  │          application.properties
│  │          spring.xml
│  │          
│  └─test
│      └─java
│          └─com
│              └─spring
│                  └─sourcecode
│                      │  SourcecodeApplicationTests.java
│                      │  
│                      └─springframework
│                          │  ApiTest.java
│                          │  
│                          └─test
│                              └─event
│                                      ContextClosedEventListener.java
│                                      ContextRefreshedEventListener.java
│                                      CustomEvent.java
│                                      CustomEventListener.java
│                                      

2.xml类图

1.ApplicationEvent

所有事件定义的父类,对于ContextRefreshedEvent来说就是刷新事件,对于ContextClosedEvent来说就是关闭事件的定义,就是用来对事件的定义

2.ApplicationListener事件监听器

ApplicationListener是个接口,当你想要实现刷新容器时进行监听可定义刷新监听器在进行实现ApplicationListener此接口,可用来自定义监听

3.ApplicationEventMulticaster

此接口是事件广播器,主要定义几个功能,用来注册事件监听器到容器里,从容器里删除监听器, 将给定的事件多播到对应发布出去

4.ApplicationEventPublisher

事件发布的定义接口,实现类里主要是用广播器发布出去

3.代码实现

 ApplicationEvent类,继承EventObject,主要是jdk自带的事件的父类

package com.spring.sourcecode.springframework.context;

import java.util.EventObject;

/**
 * @Author df
 * @Date 2022/5/8 18:55
 * @Version 1.0
 *
 * 抽象应用事件类
 */
public abstract class ApplicationEvent extends EventObject {

    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public ApplicationEvent(Object source) {
        // 调用父类的构造方法
        super(source);
    }
}

ApplicationContextEvent

package com.spring.sourcecode.springframework.context.event;

import com.spring.sourcecode.springframework.context.ApplicationContext;
import com.spring.sourcecode.springframework.context.ApplicationEvent;

/**
 * @Author df
 * @Date 2022/5/8 19:00
 * @Version 1.0
 *
 */
public class ApplicationContextEvent extends ApplicationEvent {
    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public ApplicationContextEvent(Object source) {
        super(source);
    }

    /*public final ApplicationContext getApplicationContext() {
        return (ApplicationContext) getSource();
    }*/


}

ContextClosedEvent

package com.spring.sourcecode.springframework.context.event;

/**
 * @Author df
 * @Date 2022/5/8 20:11
 * @Version 1.0
 * // 具体的事件定义
 */
public class ContextClosedEvent extends ApplicationContextEvent {
    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public ContextClosedEvent(Object source) {
        super(source);
    }
}

ContextRefreshedEvent

package com.spring.sourcecode.springframework.context.event;

/**
 * @Author df
 * @Date 2022/5/8 20:12
 * @Version 1.0
 */
public class ContextRefreshedEvent extends ApplicationContextEvent {
    /**
     * Constructs a prototypical Event.
     *
     * @param source The object on which the Event initially occurred.
     * @throws IllegalArgumentException if source is null.
     */
    public ContextRefreshedEvent(Object source) {
        super(source);
    }
}

ApplicationEventMulticaster:定义事件广播器

package com.spring.sourcecode.springframework.context.event;

import com.spring.sourcecode.springframework.context.ApplicationEvent;
import com.spring.sourcecode.springframework.context.ApplicationListener;

/**
 * @Author df
 * @Date 2022/5/8 20:54
 * @Version 1.0
 */

// 事件广播器
public interface ApplicationEventMulticaster {
    // 添加要通知所有事件的监听器
    void addApplicationListener(ApplicationListener<?> listener);
    // 从通知列表中删除监听器
    void removeApplicationListener(ApplicationListener<?> listener);
    // 将给定的应用程序事件多播到适当的监听器
    void multicastEvent(ApplicationEvent applicationEvent);
}

AbstractApplicationEventMulticaster:定义抽象类实现ApplicationEventMulticaster类的部分实现,如addApplicationListener和removeApplicationListener。此类中还定义了getApplicationListeners(),主要是获取容器中所有的监听器是否符合你给定的监听事件,符合的进行返回,并调用对应的监听实现。

package com.spring.sourcecode.springframework.context.event;

import com.spring.sourcecode.springframework.beans.BeansException;
import com.spring.sourcecode.springframework.beans.factory.BeanFactory;
import com.spring.sourcecode.springframework.beans.factory.BeanFactoryAware;
import com.spring.sourcecode.springframework.context.ApplicationEvent;
import com.spring.sourcecode.springframework.context.ApplicationListener;
import org.springframework.util.ClassUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Set;

/**
 * @Author df
 * @Date 2022/5/13 10:38
 * @Version 1.0
 */
public abstract class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster {

    private final Set<ApplicationListener<ApplicationEvent>> applicationListeners = new LinkedHashSet<>();


   /* @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }*/

    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
        applicationListeners.add((ApplicationListener<ApplicationEvent>) listener);
    }

    @Override
    public void removeApplicationListener(ApplicationListener<?> listener) {
        applicationListeners.remove(listener);
    }



    // 摘取符合广播事件中的监听处理器,具体过滤动作在supportsEvent中
    // 1.将所有的和ApplicationListener类有关系的都存储到应用事件容器里
    // 2.比如在bean处理时刷新到容器中完成时,则刷新事件并发布刷新事件
    // 3.这时将传过来的刷新事件与之前存储容器事件进行对比
    // 4.对比成功以后就存储到list以后返回
    // 循环容器中存储的监听事件和你要发布的事件是否一致
    protected Collection<ApplicationListener> getApplicationListeners(ApplicationEvent event) {
        LinkedList<ApplicationListener> allListeners = new LinkedList<ApplicationListener>();
        for (ApplicationListener<ApplicationEvent> listener : applicationListeners) {
            if (supportsEvent(listener, event)) allListeners.add(listener);
        }
        return allListeners;
    }

    /**
     * 监听器是否对该事件感兴趣
     */
    protected boolean supportsEvent(ApplicationListener<ApplicationEvent> applicationListener, ApplicationEvent event) {
        Class<? extends ApplicationListener> listenerClass = applicationListener.getClass();

        // 按照 CglibSubclassingInstantiationStrategy、SimpleInstantiationStrategy 不同的实例化类型,需要判断后获取目标 class
        Class<?> targetClass = ClassUtils.isCglibProxyClass(listenerClass) ? listenerClass.getSuperclass() : listenerClass;
        Type genericInterface = targetClass.getGenericInterfaces()[0];

        Type actualTypeArgument = ((ParameterizedType) genericInterface).getActualTypeArguments()[0];
        String className = actualTypeArgument.getTypeName();
        Class<?> eventClassName;
        try {
            eventClassName = Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw new BeansException("wrong event class name: " + className);
        }
        // 判定此 eventClassName 对象所表示的类或接口与指定的 event.getClass() 参数所表示的类或接口是否相同,或是否是其超类或超接口。
        // isAssignableFrom是用来判断子类和父类的关系的,或者接口的实现类和接口的关系的,默认所有的类的终极父类都是Object。如果A.isAssignableFrom(B)结果是true,证明B可以转换成为A,也就是A可以由B转换而来。
        return eventClassName.isAssignableFrom(event.getClass());
    }
    
}

SimpleApplicationEventMulticaster:此类继承AbstractApplicationEventMulticaster广播器,当是匹配的监听器,实现发布广播。

package com.spring.sourcecode.springframework.context.event;

import com.spring.sourcecode.springframework.beans.factory.BeanFactory;
import com.spring.sourcecode.springframework.context.ApplicationEvent;
import com.spring.sourcecode.springframework.context.ApplicationListener;

/**
 * @Author df
 * @Date 2022/5/13 10:58
 * @Version 1.0
 */
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {

    // 调用实现的事件处理器
    @Override
    public void multicastEvent(final ApplicationEvent applicationEvent) {
        for (final ApplicationListener listener : getApplicationListeners(applicationEvent)) {
            listener.onApplicationEvent(applicationEvent);
        }
    }
}

ApplicationEventPublisher:事件发布定义

/**
 * @Author df
 * @Date 2022/5/13 10:46
 * @Version 1.0
 * // 事件发布者定义
 */
public interface ApplicationEventPublisher {
    void publishEvent(ApplicationEvent event);
}

AbstractApplicationContext部分实现,只添加本节添加的东西,添加了初始化广播器

以及注册事件监听器,发布刷新容器,和关闭容器

  @Override
    public void refresh() {

        // 6.
        initApplicationEventMulticaster();

        // 7.注册事件监听器
        registerListeners();

        // 8.提前实例化单例bean对象
        // 通过beanDefinationMap里的实例对象将后续bean实例进行实例化,并处理后置修改的对象
        beanFactory.preInstantiateSingletons();

        // 9. 发布容器刷新完成事件
        finishRefresh();

    }

 private void initApplicationEventMulticaster() {
        //ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        applicationEventMulticaster = new SimpleApplicationEventMulticaster();
        //beanFactory
    }

    // 将配置文件的关于监听的配置进行注册存储容器里
    private void registerListeners() {
        Collection<ApplicationListener> applicationListeners = getBeansOfType(ApplicationListener.class).values();
        for (ApplicationListener listener : applicationListeners) {
            applicationEventMulticaster.addApplicationListener(listener);
        }
    }

    private void finishRefresh() {
        publishEvent(new ContextRefreshedEvent(this));
    }

    @Override
    public void publishEvent(ApplicationEvent event) {
        applicationEventMulticaster.multicastEvent(event);
    }


  @Override
    public void close() {
        // 发布容器关闭事件
        publishEvent(new ContextClosedEvent(this));

        getBeanFactory().destroySingletons();
    }

4.测试准备

4.1 创建一个自定义事件和监听器

package com.spring.sourcecode.springframework.test.event;

import com.spring.sourcecode.springframework.context.event.ApplicationContextEvent;

/**
 * @Author df
 * @Date 2022/5/13 11:24
 * @Version 1.0
 */
public class CustomEvent extends ApplicationContextEvent {
    private Long id;
    private String message;

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

   // 省略set/get
}

自定义事件监听器

package com.spring.sourcecode.springframework.test.event;

import com.spring.sourcecode.springframework.context.ApplicationListener;

import java.util.Date;

/**
 * @Author df
 * @Date 2022/5/13 11:27
 * @Version 1.0
 */
public class CustomEventListener implements ApplicationListener<CustomEvent> {
    @Override
    public void onApplicationEvent(CustomEvent event) {
        System.out.println("收到:" + event.getSource() + "消息;时间:" + new Date());
        System.out.println("消息:" + event.getId() + ":" + event.getMessage());
    }
}

4.2 创建一个容器刷新事件监听器

package com.spring.sourcecode.springframework.test.event;

import com.spring.sourcecode.springframework.context.ApplicationListener;
import com.spring.sourcecode.springframework.context.event.ContextRefreshedEvent;

/**
 * @Author df
 * @Date 2022/5/13 11:52
 * @Version 1.0
 */
public class ContextRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("刷新事件");
    }
}

4.3 创建一个事件关闭监听处理器

package com.spring.sourcecode.springframework.test.event;

import com.spring.sourcecode.springframework.context.ApplicationListener;
import com.spring.sourcecode.springframework.context.event.ContextRefreshedEvent;

/**
 * @Author df
 * @Date 2022/5/13 11:52
 * @Version 1.0
 */
public class ContextRefreshedEventListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println("刷新事件");
    }
}

4.4 配置文件,将几个监听器配置进来

<?xml version="1.0" encoding="UTF-8" ?>
<beans>
    <bean class="com.spring.sourcecode.springframework.test.event.CustomEventListener">
    </bean>

    <bean class="com.spring.sourcecode.springframework.test.event.ContextClosedEventListener">
    </bean>

    <bean class="com.spring.sourcecode.springframework.test.event.ContextRefreshedEventListener">
    </bean>
</beans>

4.5 单元测试

public class ApiTest {
    //
    @Test
    public void testFactoryBean() {
        // 1.初始化BeanFactory
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring.xml");
        applicationContext.publishEvent(new CustomEvent(applicationContext, 1019129009086763L, "成功了!"));
        applicationContext.registerShutdownHook();
    }
}

5.测试结果

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值