spring内部事件源码(上) ApplicationEvent

        本文章介绍spring内部事件是如何发布,监听消息是怎么消费的。

一般来说spring发布事件,监听器接收并执行,是同步的。这样写虽然代码分离,但同步执行时间就会增加,想改为异步执行,在监听方法上加@Async注解。

目录

测试代码

发布消息

 监听消息

spring事件源码分析


自己新建一个springboot项目

测试代码

发布消息


import com.example.demo2.AppConfig;
import com.example.demo2.domain.dto.AnaimalEvent;
import com.example.demo2.domain.dto.Dog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @Author wfl 2021/12/10
 * 功能
 */
@Slf4j
public class UserListener {

    public static void main(String[] args) {
        // 创建spring 容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        Dog dog = new Dog();
        dog.setAddr("aa");
        dog.setName("eventlistener");
        context.publishEvent(dog);

        Dog dog2 = new Dog();
        dog2.setAddr("cc");
        dog2.setName("Applicationlistener");
        AnaimalEvent event = new AnaimalEvent(dog2);
        context.publishEvent(event);
        
        log.info("jjjjj");
        context.close();
    }
}

以上发布了2中事件,一种是继承ApplicationEvent类的AnaimalEvent。一种是Dog类。

监听事件也是2种形式,1实现了ApplicationListener;

2. 使用注解@EventListener      org.springframework.context.event.EventListener

或者@TransactionalEventListener  org.springframework.transaction.event.TransactionalEventListener;

 监听消息

注解监听


import com.example.demo2.domain.dto.Dog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * @Author wfl 2021/12/10
 * 功能
 */
@Component
@Slf4j
public class AnaimalEventListen {

    //这个asyncGmOrderHttpExecutor 是自定义的,可以删除,使用springboot默认的
    @Async("asyncGmOrderHttpExecutor")
    @EventListener
    public void hanlderAnaimal(Dog dog){
        System.out.println(Thread.currentThread().getName() + "=====注解监听===");
        log.info("llllll");
    }
}

实现监听器

import com.example.demo2.domain.dto.AnaimalEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

/**
 * @Author wfl 2021/12/14
 * 功能
 */
@Component
public class MyAnaimalListener implements ApplicationListener {
    @Override
    public void onApplicationEvent(AnaimalEvent event) {
        System.out.println("实现监听器----"+event);
    }
}

其他实体类

import lombok.Data;

/**
 * @Author wfl 2021/12/10
 * 功能
 */
@Data
public class Dog extends Anaimal{
    private String name;
}
import lombok.Data;
import org.springframework.context.ApplicationEvent;

import java.time.Clock;

/**
 * @Author wfl 2021/12/10
 * 功能
 */
@Data
public class Anaimal {
    private String addr;
}
import org.springframework.context.ApplicationEvent;

/**
 * @Author wfl 2021/12/10
 * 功能
 */
public class AnaimalEvent extends ApplicationEvent {
    private String addr;

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

配置类

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

/**
 * @Author wfl 2021/12/10
 * 功能 配置类,开启异步功能
 */
@Configuration
@ComponentScan("com.*")
@EnableAsync
public class AppConfig {
}

以上代码就可以运行,实现发布事件,监听事件。项目需要注入事件发布类

ApplicationContext
@RestController
@RequestMapping(value = "/user" )
public class UserController {

    @Resource
    private ApplicationContext applicationContext;

@GetMapping("/a")
    public int accountAdssd(){
        Anaimal dog = new Dog();
        dog.setAddr("aa");
        applicationContext.publishEvent(dog);
        return 2;
    }
}

spring事件源码分析

下面介绍源码执行过程

先从事件发布入手。applicationContext.publishEvent(dog);

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
//...............省略代码

    //发布事件方法
    public void publishEvent(Object event) {
        this.publishEvent(event, (ResolvableType)null);
    }

    protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
        Assert.notNull(event, "Event must not be null");
        Object applicationEvent;
//处理第二种实现ApplicationEvent类的事件
        if (event instanceof ApplicationEvent) {
            applicationEvent = (ApplicationEvent)event;
        } else {
            applicationEvent = new PayloadApplicationEvent(this, event);
            if (eventType == null) {
                eventType = ((PayloadApplicationEvent)applicationEvent).getResolvableType();
            }
        }

        if (this.earlyApplicationEvents != null) {
            this.earlyApplicationEvents.add(applicationEvent);
        } else {
//上面是一些判断处理,最后会走到这。   this.getApplicationEventMulticaster()获取事件发布器。再发布         
this.getApplicationEventMulticaster().multicastEvent((ApplicationEvent)applicationEvent, eventType);
        }

        if (this.parent != null) {
            if (this.parent instanceof AbstractApplicationContext) {
                ((AbstractApplicationContext)this.parent).publishEvent(event, eventType);
            } else {
                this.parent.publishEvent(event);
            }
        }

    }
}
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
	@Override
	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		Executor executor = getTaskExecutor();
		for (ApplicationListener listener : getApplicationListeners(event, type)) {
            // 这个异步执行器一般是空的。
			if (executor != null) {
				executor.execute(() -> invokeListener(listener, event));
			}
			else {
                // 会执行这个反射 这里体现的就是同步执行
//其中这个listener 就会分两种,一种注解的,
//被ApplicationListenerMethodAdapter包装的监听类
//另一种是实现监听的,下面加载的时候会介绍
				invokeListener(listener, event);
			}
		}
	}
}

这里会同步执行消息处理,如果要异步加@Async注解实现。

invokeListener(ApplicationListener listener, ApplicationEvent event)----》
doInvokeListener(listener, event);----->
listener.onApplicationEvent(event);这里的listener是ApplicationListenerMethodAdapter打开这个类找到onApplicationEvent(event)方法;----->
processEvent(event);
/**
	 * Process the specified {@link ApplicationEvent}, checking if the condition
	 * matches and handling a non-null result, if any.
	 */
	public void processEvent(ApplicationEvent event) {
		Object[] args = resolveArguments(event);
		if (shouldHandle(event, args)) {
			Object result = doInvoke(args);
			if (result != null) {
				handleResult(result);
			}
			else {
				logger.trace("No result object given - no result to handle");
			}
		}
	}

然后执行

Object result = doInvoke(args);----》反射执行,有返回结果result会接收到。---》
protected Object doInvoke(Object... args){ 
        //这个bean是从spring中拿到的监听类
        Object bean = this.getTargetBean();
        //省略代码.... 
       try {
                //反射执行
                   return this.method.invoke(bean, args);
           }
}

此时还在ApplicationListenerMethodAdapter这个类中,大约在342行源码。

断点调试图@EventListener执行过程

spring内部事件源码(上) ApplicationEvent_第1张图片

spring内部事件源码(上) ApplicationEvent_第2张图片

 实现监听调试class MyAnaimalListener implements ApplicationListener

spring内部事件源码(上) ApplicationEvent_第3张图片

spring内部事件源码(上) ApplicationEvent_第4张图片

 下面是复杂的加异步注解的调试

加异步注解后返回的是异步执行代理类这里与没加异步注解返回的bean是不一样的

spring内部事件源码(上) ApplicationEvent_第5张图片

构建一个代理,执行proceed() 进入异步拦截器执行

spring内部事件源码(上) ApplicationEvent_第6张图片

下图,开始提交任务,异步执行 

spring内部事件源码(上) ApplicationEvent_第7张图片

 这里,事件发布介绍完了。

监听如何加载的另一篇文章介绍。

https://blog.csdn.net/wangfenglei123456/article/details/121930345icon-default.png?t=LA92https://blog.csdn.net/wangfenglei123456/article/details/121930345

你可能感兴趣的:(spring源码,spring)