Spring事件监听器之@EventListener原理

简介

Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式;为的就是业务系统逻辑的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。

在spring中我们可以通过实现ApplicationListener接口或者@EventListener接口来实现事件驱动编程

比如我们做一个电商系统,用户下单支付成功后,我们一般要发短信或者邮箱给用户提示什么的,这时候就可以把这个通知业务做成一个单独事件监听,等待通知就可以了;把它解耦处理。

public class OrderEvent extends ApplicationEvent {

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

}

@Component
public class OrderEventListener  {

    @EventListener
    public void listener(OrderEvent event) {
        System.out.println("i do OrderEventListener" );
    }
}


@Controller
@RequestMapping("person")
public class PersonController implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @ResponseBody
    @GetMapping("publishOrderEvent")
    public String publishOrderEvent() {
        applicationContext.publishEvent(new OrderEvent("我发布了事件!!!"));
        System.out.println(" publishOrderEvent ");
        return "发送事件了!";
    }
}

EventListenerMethodProcessor是@EventListener的解析类,他是一个SmartInitializingSingleton和BeanFactoryPostProcessor

一、解析@EventListener前的准备工作
1.1 EventListenerFactory和EventListenerMethodProcessor的注入

EventListenerFactory是把@EventListener标注的方法变成ApplicationListener的关键,其是在容器最初期(refresh方法发生前)就放到容器中去l

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors( BeanDefinitionRegistry registry, Object source) {
        //获取对象
		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		
        //org.springframework.context.event.internalEventListenerProcessor
        //@EventListener注解处理器
		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}
        //org.springframework.context.event.internalEventListenerProcessor
        //内部管理的EventListenerFactory的bean名称
		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}
		return beanDefs;
	}

如果容器中没有名字是org.springframework.context.event.internalEventListenerProcessor的bean,那么就注入一个EventListenerMethodProcessor到容器中

如果容器中没有名字是org.springframework.context.event.internalEventListenerProcessor的bean,那么就注入一个DefaultEventListenerFactory到容器中

1.2 EventListenerMethodProcessor和EventListenerFactory关系的建立

EventListenerMethodProcessor会在容器启动时被注入到容器中,他是一个BeanFactoryPostProcessor,EventListenerMethodProcessor和EventListenerFactory关系的建立就发生在其方法postProcessBeanFactory中

public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {

	@Nullable
	private List<EventListenerFactory> eventListenerFactories;

    //初始化eventListenerFactories
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		this.beanFactory = beanFactory;
		//获取容器中所有的EventListenerFactory,并把他们实例化
		Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
		
		List<EventListenerFactory> factories = new ArrayList<>(beans.values());
		AnnotationAwareOrderComparator.sort(factories);
		//将EventListenerFactory储存到缓存eventListenerFactories中,便于后来使用
		this.eventListenerFactories = factories;
	}
}

EventListenerFactory的实例化时机只比BeanFactoryPostProcessor完点,他比BeanPostProcessor实例化时机早

二、开始解析@EventListener

EventListenerMethodProcessor是一个SmartInitializingSingleton,所以他会在所以bean实例化后,执行其afterSingletonsInstantiated方法

注意:只有单例的SmartInitializingSingleton,才会执行其afterSingletonsInstantiated方法

2.1 基本流程
public class EventListenerMethodProcessor implements SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor {

    @Override
	public void afterSingletonsInstantiated() {
		ConfigurableListableBeanFactory beanFactory = this.beanFactory;
		Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
		// 这里厉害了,用Object.class 是拿出容器里面所有的Bean定义~~~  一个一个的检查
		String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
		for (String beanName : beanNames) {
		     // 
			if (!ScopedProxyUtils.isScopedTarget(beanName)) {
				Class<?> type = null;
				try {
				     // 防止是代理,吧真实的类型拿出来
					type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
				}
				catch (Throwable ex) {
					if (logger.isDebugEnabled()) {
						logger.debug("", ex);
					}
				}
				if (type != null) {
				    // 对专门的作用域对象进行兼容~~~~(绝大部分都用不着)
					if (ScopedObject.class.isAssignableFrom(type)) {
						try {
							Class<?> targetClass = AutoProxyUtils.determineTargetClass(
									beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
							if (targetClass != null) {
								type = targetClass;
							}
						}
						catch (Throwable ex) {
							// An invalid scoped proxy arrangement - let's ignore it.
							if (logger.isDebugEnabled()) {
								logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
							}
						}
					}
					try {
					    // 真正处理这个Bean里面的方法们。。。
						processBean(beanName, type);
					}
					catch (Throwable ex) {
						throw new BeanInitializationException("", ex);
					}
				}
			}
		}
	}

	private void processBean(final String beanName, final Class<?> targetType) {
	         //类上有@Component注解
			if (!this.nonAnnotatedClasses.contains(targetType) &&!targetType.getName().startsWith("java") &&!isSpringContainerClass(targetType)) {
	 			Map<Method, EventListener> annotatedMethods = null;
				try {
				    //获取类中用@EventListener标注方法的信息
					annotatedMethods = MethodIntrospector.selectMethods(targetType,
							(MethodIntrospector.MetadataLookup<EventListener>) method ->
									AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
				}
				catch (Throwable ex) {
					// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
					if (logger.isDebugEnabled()) {
						logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
					}
				}
	            //如果annotatedMethods为空,那代表类中没有用@EventListener标注的方法
				if (CollectionUtils.isEmpty(annotatedMethods)) {
					this.nonAnnotatedClasses.add(targetType);
					if (logger.isTraceEnabled()) {
						logger.trace("" + targetType.getName());
					}
				}
				else {
					// 类中存在用@EventListener标注的方法
					ConfigurableApplicationContext context = this.applicationContext;
					Assert.state(context != null, "No ApplicationContext set");
					//获取容器中所有EventListenerFactory
					List<EventListenerFactory> factories = this.eventListenerFactories;
					Assert.state(factories != null, "EventListenerFactory List not initialized");
					for (Method method : annotatedMethods.keySet()) {
						for (EventListenerFactory factory : factories) {
							if (factory.supportsMethod(method)) {
								// 简单的说,就是把这个方法弄成一个可以执行的方法(主要和访问权限有关)
							  // 这里注意:若你是JDK的代理类,请不要在实现类里书写@EventListener注解的监听器,否则会报错的。(CGLIB代理的木关系) 
								Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName)); 

                                //利用EventListenerFactory创建ApplicationListener,详情后面说
								ApplicationListener<?> applicationListener =
										factory.createApplicationListener(beanName, targetType, methodToUse);
								//如果ApplicationListener是ApplicationListenerMethodAdapter类,那么执行其init方法
								if (applicationListener instanceof ApplicationListenerMethodAdapter) {
									((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
								}
								//放到容器中
								context.addApplicationListener(applicationListener);
								//@EventListener方法只能解析一次
								break;
							}
						}
					}
					if (logger.isDebugEnabled()) {
						logger.debug();
					}
				}
			}
		}
}	

获取容器中所有的类,把用@Component标注的类上所有的@EventListener方法用EventListenerFactory解析成一个ApplicationListener

@EventListener方法只要有到一个可以解析他的EventListenerFactory,就不会让其他EventListenerFactory解析他了
所以如果容器中存在多个EventListenerFactory,我要注意他的顺序

2.2 EventListenerFactory解析@EventListener

在这里插入图片描述

public interface EventListenerFactory {
    //是否支持当前方法
	boolean supportsMethod(Method method);
	
	//生成一个ApplicationListener
	ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method);

}

EventListenerFactory有2个字类DefaultEventListenerFactory和TransactionalEventListenerFactory,DefaultEventListenerFactory是处理@EventListener,而TransactionalEventListenerFactory是处理@TransactionalEventListener的,Spring默认就有DefaultEventListenerFactory,而TransactionalEventListenerFactory是没有的,所以我们想要支持@TransactionalEventListener,就要注册一个TransactionalEventListenerFactory,也就是要说要使用@EnableTransactionManagement注解

public class DefaultEventListenerFactory implements EventListenerFactory, Ordered {

	private int order = LOWEST_PRECEDENCE;

	@Override
	public boolean supportsMethod(Method method) {
		return true;
	}

	@Override
	public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
		return new ApplicationListenerMethodAdapter(beanName, type, method);
	}

}

ApplicationListenerMethodAdapter一个ApplicationListener,他是用来包装@EventListener标注的方法

public class ApplicationListenerMethodAdapter implements GenericApplicationListener {

	private final String beanName; //@EventListener方法所属bean的名字
	private final Method method;//@EventListener标注的方法
	private final Method targetMethod;//@EventListener标注的真实方法对象,防止其是代理方法
    //方法申明,如public void demo.Ball.applicationContextEvent(demo.OrderEvent)
	private final AnnotatedElementKey methodKey;
	private final List<ResolvableType> declaredEventTypes;//存储方法的参数
	private final String condition;//@EventListener的condition
	private final int order;
	private ApplicationContext applicationContext;
	private EventExpressionEvaluator evaluator;//@EventListener的EventExpressionEvaluator


	public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, Method method) {
		this.beanName = beanName;
		this.method = BridgeMethodResolver.findBridgedMethod(method);
		this.targetMethod = (!Proxy.isProxyClass(targetClass) ?AopUtils.getMostSpecificMethod(method, targetClass) : this.method);
		this.methodKey = new AnnotatedElementKey(this.targetMethod, targetClass);
		//获取方法上的@EventListener注解对象
		EventListener ann = AnnotatedElementUtils.findMergedAnnotation(this.targetMethod, EventListener.class);
		this.declaredEventTypes = resolveDeclaredEventTypes(method, ann);
		this.condition = (ann != null ? ann.condition() : null);
		this.order = resolveOrder(this.targetMethod);
	}

    public void onApplicationEvent(ApplicationEvent event) {
		processEvent(event);
	}
	
    public void processEvent(ApplicationEvent event) {
		Object[] args = resolveArguments(event);
		//根据@EventListener的condition,判断是否要处理
		if (shouldHandle(event, args)) {
		    //调用方法
			Object result = doInvoke(args);
			if (result != null) {
			    //如果有监听器可以监听这个结果,那么可以触发那个监听器
				handleResult(result);
			}
			else {
				logger.trace("No result object given - no result to handle");
			}
		}
	}
}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值