ApplicationListener机制

Posted 恒奇恒毅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ApplicationListener机制相关的知识,希望对你有一定的参考价值。

EventListener注解支持

什么时候解析EventListener注解?

EventListener注解由EventListenerMethodProcessor进行解析。
EventListenerMethodProcessor实现了SmartInitializingSingleton,在方法afterSingletonsInstantiated中对EventListener进行处理。

	@Override
	public void afterSingletonsInstantiated() 
		List<EventListenerFactory> factories = getEventListenerFactories();
		String[] beanNames = this.applicationContext.getBeanNamesForType(Object.class);
		for (String beanName : beanNames) 
			if (!ScopedProxyUtils.isScopedTarget(beanName)) 
				Class<?> type = null;
				try 
					type = AutoProxyUtils.determineTargetClass(this.applicationContext.getBeanFactory(), beanName);
				
				catch (Throwable ex) 
					// An unresolvable bean type, probably from a lazy bean - let's ignore it.
					if (logger.isDebugEnabled()) 
						logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
					
				
				if (type != null) 
					if (ScopedObject.class.isAssignableFrom(type)) 
						try 
							type = AutoProxyUtils.determineTargetClass(this.applicationContext.getBeanFactory(),
									ScopedProxyUtils.getTargetBeanName(beanName));
						
						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 
						processBean(factories, beanName, type);
					
					catch (Throwable ex) 
						throw new BeanInitializationException("Failed to process @EventListener " +
								"annotation on bean with name '" + beanName + "'", ex);
					
				
			
		
	


	/**
	 * Return the @link EventListenerFactory instances to use to handle
	 * @link EventListener annotated methods.
	 */
	protected List<EventListenerFactory> getEventListenerFactories() 
		Map<String, EventListenerFactory> beans = this.applicationContext.getBeansOfType(EventListenerFactory.class);
		List<EventListenerFactory> allFactories = new ArrayList<EventListenerFactory>(beans.values());
		AnnotationAwareOrderComparator.sort(allFactories);
		return allFactories;
	

	protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) 
		if (!this.nonAnnotatedClasses.contains(targetType)) 
			Map<Method, EventListener> annotatedMethods = null;
			try 
				annotatedMethods = MethodIntrospector.selectMethods(targetType,
						new MethodIntrospector.MetadataLookup<EventListener>() 
							@Override
							public EventListener inspect(Method method) 
								return 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);
				
			
			if (CollectionUtils.isEmpty(annotatedMethods)) 
				this.nonAnnotatedClasses.add(targetType);
				if (logger.isTraceEnabled()) 
					logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
				
			
			else 
				// Non-empty set of methods
				for (Method method : annotatedMethods.keySet()) 
					for (EventListenerFactory factory : factories) 
						if (factory.supportsMethod(method)) 
							Method methodToUse = AopUtils.selectInvocableMethod(
									method, this.applicationContext.getType(beanName));
							ApplicationListener<?> applicationListener =
									factory.createApplicationListener(beanName, targetType, methodToUse);
							if (applicationListener instanceof ApplicationListenerMethodAdapter) 
								((ApplicationListenerMethodAdapter) applicationListener)
										.init(this.applicationContext, this.evaluator);
							
							this.applicationContext.addApplicationListener(applicationListener);
							break;
						
					
				
				if (logger.isDebugEnabled()) 
					logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
							beanName + "': " + annotatedMethods);
				
			
		
	

首先从容器中获取EventListenerFactory的实现类,用于产生ApplicationListener。然后获取容器中的所有bean进行EventListener解析。
在processBean方法中,对所有Bean的所有标注了EventListener的方法进行遍历,所有的EventListenerFactory产生一个ApplicationListener,通过ApplicationConetxt#addApplicationListener放入容器中,底层实现加入了SimpleApplicationEventMulticaster

Method methodToUse = AopUtils.selectInvocableMethod(
									method, this.applicationContext.getType(beanName));
							ApplicationListener<?> applicationListener =
									factory.createApplicationListener(beanName, targetType, methodToUse);
							if (applicationListener instanceof ApplicationListenerMethodAdapter) 
								((ApplicationListenerMethodAdapter) applicationListener)
										.init(this.applicationContext, this.evaluator);
							
							this.applicationContext.addApplicationListener(applicationListener);

系统默认的EventListenerFactoryDefaultEventListenerFactory,和EventListenerMethodProcessor都是在org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)方法中注册的这个类。说实在的EventListenerFactory叫ApplicationListenerFactory是不是更好呢?

		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));
		
		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));
		

以上是关于ApplicationListener机制的主要内容,如果未能解决你的问题,请参考以下文章

ApplicationListener机制

ApplicationListener机制

Spring中ApplicationListener的使用

Spring中ApplicationListener的使用

ApplicationListener的使用

设计模式之-观察者模式