ApplicatoinContext.5 国际化和event机制解析

国际化和event机制是通过initMessageSource,initApplicationEventMulticaster来实现的。

两者都是查找名称为特定名称,类型为特定的类型赋值给applicationContext内部的成员变量,如果没找到则新建。

/**--org.springframework.context.support.AbstractApplicationContext--**/
protected void initMessageSource() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	//首先判断是不是存在名字为MESSAGE_SOURCE_BEAN_NAME的bean或者beanDefinition。
	if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
		//获取名称为messageSource,类型为MessageSource,并赋值给messageSource
		this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
		// Make MessageSource aware of parent MessageSource.
		if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
			HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
			if (hms.getParentMessageSource() == null) {
				// Only set parent context as parent MessageSource if no parent MessageSource
				// registered already.
				hms.setParentMessageSource(getInternalParentMessageSource());
			}
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Using MessageSource [" + this.messageSource + "]");
		}
	}
	else {
		// Use empty MessageSource to be able to accept getMessage calls.
		DelegatingMessageSource dms = new DelegatingMessageSource();
		dms.setParentMessageSource(getInternalParentMessageSource());
		this.messageSource = dms;
		beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
		if (logger.isDebugEnabled()) {
			logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
					"': using default [" + this.messageSource + "]");
		}
	}
}

国际化

  1. MessageFormat
  2. ResourceBundle
  3. MessageSource

如何使用国际化

  1. 注册一个beanName=messageSourcebean,该bean 要实现 MessageSource 方法.
  2. spring 提供了 MessageSource 的实现类 ResourceBundleMessageSource ,本质上是使用 java 自身提供的国际化实现.
  3. 实例
    <beans>
    <bean id="messageSource"
            class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>format</value>
                <value>exceptions</value>
                <value>windows</value>
            </list>
        </property>
    </bean>
    </beans>
    

The example assumes that you have three resource bundles called format_en_GB.properties, exceptions and windows defined in your classpath

EventListener

applicationContext是委托ApplicationEventMulticasterSimpleApplicationEventMulticaster完成事件监听的.最终所有的ApplicationListener队友注册到ApplicationEventMulticaster

  1. ApplicationListener接口和ApplicationEvent抽象类
  2. 4.2 版本后的EventListener注解
  3. 配置资源中的ApplicationListener接口的类是通过ApplicationListenerDetector(BeanPostProcessor的实现类)来注册到ApplicationEventMulticaster

代码

	protected void registerListeners() {
		// Register statically specified listeners first.
		for (ApplicationListener<?> listener : getApplicationListeners()) {
			getApplicationEventMulticaster().addApplicationListener(listener);
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans.此处不提前获取 `create` 对应的`Listener`. 
		// uninitialized to let post-processors apply to them!
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}

		// Publish early application events now that we finally have a multicaster...
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null;
		if (earlyEventsToProcess != null) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent);
			}
		}
	}

  1. 处理手动注册的 ApplicationListener
  2. 查询出所有的 ApplicationListenerbeanName 并注册到applicationEventMulticaster中.
  3. 如果能提前发布event , 将 earlyApplicationEvents 发布出去.

@EventListener

大致处理流程是扫描所有 实现 EventListener注解的方法,将其转化为 ApplicationListener. 转化的动作是由 EventListenerFactory 实现。

EventListenerFactory : 将方法转化为 ApplicationListener.

为什么使用EventListenerFactory 主要是可能有不同的事件类型.例如普通event事务event.两个实现类分别为TransactionalEventListenerFactoryDefaultEventListenerFactory.

EventListenerMethodProcessor 将调用EventListenerFactory 将符合条件的Method创建成ApplicationListener

EventListenerMethodProcessor

该类实现 BeanFactoryPostProcessorSmartInitializingSingleton . 其功能主要在 所有的BeanDefinition加载完毕,以及所有的 singleton类 创建完成后调用。 代码如下

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	this.beanFactory = beanFactory;

	Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
	List<EventListenerFactory> factories = new ArrayList<>(beans.values());
	AnnotationAwareOrderComparator.sort(factories);
	this.eventListenerFactories = factories;
}

BeanDefinition加载完毕后,调用beanFactory 提前创建所有实现了 EventListenerFactorybean.

AnnotationConfigUtils.registerAnnotationConfigProcessors 会设置 DefaultEventListenerFactory.

在所有的singleton创建完成后,

  1. 遍历所有的singleton
  2. 如果bean不是 scopedTarge.(不知道干啥的)
  3. 判断beanclass.(注意代理类的class获取,使用AutoProxyUtils类获取代理类的class)
  4. 如果是class实现了ScopedObject,特殊处理下(不知道干啥)
  5. 扫描所有满足条件的method 调用 EventListenerFactory 生成ApplicationListener

@Override
public void afterSingletonsInstantiated() {
	ConfigurableListableBeanFactory beanFactory = this.beanFactory;
	Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
	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) {
				// 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 {
						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 {
				    //创建方法
					processBean(beanName, type);
				}
				catch (Throwable ex) {
					throw new BeanInitializationException("Failed to process @EventListener " +
							"annotation on bean with name '" + beanName + "'", ex);
				}
			}
		}
	}
}

processBean

  1. 寻找所有@EventListener 的方法。
  2. 通过EventListenerFactory 来创建 ApplicationListener(默认都是ApplicationListenerMethodAdapter)
  3. 注册到applicationContext中。

private void processBean(final String beanName, final Class<?> targetType) {
	if (!this.nonAnnotatedClasses.contains(targetType) &&
			AnnotationUtils.isCandidateClass(targetType, EventListener.class) &&
			!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);
			}
		}
        //如果没有相应的方法,缓存下来。避免下次判断
		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
			ConfigurableApplicationContext context = this.applicationContext;
			Assert.state(context != null, "No ApplicationContext set");
			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)) {
						Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
						//调用EventListenerFactory 生成  ApplicationListener
						ApplicationListener<?> applicationListener =
								factory.createApplicationListener(beanName, targetType, methodToUse);
						if (applicationListener instanceof ApplicationListenerMethodAdapter) {
							((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
						}
						context.addApplicationListener(applicationListener);
						break;
					}
				}
			}
			if (logger.isDebugEnabled()) {
				logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
						beanName + "': " + annotatedMethods);
			}
		}
	}
}

如何通过事件找到对应的applicationListenner

通常我们发布事件都是之间通过applicationContext.publishEvent() 或者 注入一个 ApplicationEventMulticaster 来 发布事件的。本质上都是调用 applicationContext.applicationEventMulticaster.publishEvent(Object event, @Nullable ResolvableType eventType) 来发布事件。只不过 applicationContext.publishEvent() 使用了包装模式 能够将普通的对象转化为applicationEvent

  1. 事件分为两种。 一种是直接实现了ApplicationEvent,一种就是原始的object
  2. 对于ApplicationEvent不需要直接处理发布,对于未实现的,需要解析出eventType , 用来匹配applicationListenner
  3. 事件也会在parent中发布
  4. 事件会在支持对应 event Listenner中调用。

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
	Assert.notNull(event, "Event must not be null");

	// Decorate event as an ApplicationEvent if necessary
	ApplicationEvent applicationEvent;
	if (event instanceof ApplicationEvent) {
		applicationEvent = (ApplicationEvent) event;
	}
	else {
		applicationEvent = new PayloadApplicationEvent<>(this, event);
		if (eventType == null) {
			eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
		}
	}

	// Multicast right now if possible - or lazily once the multicaster is initialized
	if (this.earlyApplicationEvents != null) {
		this.earlyApplicationEvents.add(applicationEvent);
	}
	else {
		getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
	}

	// Publish event via parent context as well...
	if (this.parent != null) {
		if (this.parent instanceof AbstractApplicationContext) {
			((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
		}
		else {
			this.parent.publishEvent(event);
		}
	}
}

查找满足条件的listener的方法为 org.springframework.context.event.AbstractApplicationEventMulticaster#getApplicationListeners(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType) ,

其中判断listener 是否支持相应event的方法是 org.springframework.context.event.AbstractApplicationEventMulticaster#supportsEvent(org.springframework.context.ApplicationListener<?>, org.springframework.core.ResolvableType, java.lang.Class<?>),

supportsEvent最终是调用GenericApplicationListener 里面的 supportsEventTypesupportsSourceType 来判断是否支持的. 而 ApplicationListenerMethodAdapter 实现了 GenericApplicationListener

我们假设事件为A.class的对象. 则对应的 applicationEvent = new PayloadApplicationEvent(context,a).对应的eventType = ResolvableType.forClassWithGenerics(applicationContext.class,A.class)


protected Collection<ApplicationListener<?>> getApplicationListeners(
		ApplicationEvent event, ResolvableType eventType) {
    
    //source = a 
	Object source = event.getSource();
	//sourceType=A.class
	Class<?> sourceType = (source != null ? source.getClass() : null);
	ListenerCacheKey cacheKey = new ListenerCacheKey(eventType, sourceType);

	// Quick check for existing entry on ConcurrentHashMap...
	//从缓存获取,缓存中没有 通过 retrieveApplicationListeners 方法获取
	ListenerRetriever retriever = this.retrieverCache.get(cacheKey);
	if (retriever != null) {
		return retriever.getApplicationListeners();
	}

	if (this.beanClassLoader == null ||
			(ClassUtils.isCacheSafe(event.getClass(), this.beanClassLoader) &&
					(sourceType == null || ClassUtils.isCacheSafe(sourceType, this.beanClassLoader)))) {
		// Fully synchronized building and caching of a ListenerRetriever
		synchronized (this.retrievalMutex) {
			retriever = this.retrieverCache.get(cacheKey);
			if (retriever != null) {
				return retriever.getApplicationListeners();
			}
			retriever = new ListenerRetriever(true);
			Collection<ApplicationListener<?>> listeners =
					retrieveApplicationListeners(eventType, sourceType, retriever);
			this.retrieverCache.put(cacheKey, retriever);
			return listeners;
		}
	}
	else {
		// No ListenerRetriever caching -> no synchronization necessary
		return retrieveApplicationListeners(eventType, sourceType, null);
	}
}

private Collection<ApplicationListener<?>> retrieveApplicationListeners(
		ResolvableType eventType, Class<?> sourceType, ListenerRetriever retriever) {
....
	for (ApplicationListener<?> listener : listeners) {
		if (supportsEvent(listener, eventType, sourceType)) {
			if (retriever != null) {
				retriever.applicationListeners.add(listener);
			}
			allListeners.add(listener);
		}
	}
	if (!listenerBeans.isEmpty()) {
		BeanFactory beanFactory = getBeanFactory();
		for (String listenerBeanName : listenerBeans) {
			try {
				Class<?> listenerType = beanFactory.getType(listenerBeanName);
				if (listenerType == null || supportsEvent(listenerType, eventType)) {
					ApplicationListener<?> listener =
							beanFactory.getBean(listenerBeanName, ApplicationListener.class);
					if (!allListeners.contains(listener) && supportsEvent(listener, eventType, sourceType)) {
						if (retriever != null) {
							retriever.applicationListenerBeans.add(listenerBeanName);
						}
						allListeners.add(listener);
					}
				}
			}
			catch (NoSuchBeanDefinitionException ex) {
			...
			}
		}
	}
	AnnotationAwareOrderComparator.sort(allListeners);
	return allListeners;
}

//org.springframework.context.event.ApplicationListenerMethodAdapter#supportsEventType
//eventType = ResolvableType.forClassWithGenerics(applicationContext.class,A.class)
public boolean supportsEventType(ResolvableType eventType) {
	for (ResolvableType declaredEventType : this.declaredEventTypes) {
	   //declaredEventTypes 是冲 @EventListener注解中获取的 ResolvableType.forClass 和 监听方法参数中的 ResolvableType.forMethodParameter. 
	   //而 eventType 的 是raw class = PayloadApplicationEvent.class,
	   //泛型参数为 A.class的 ResolvableType . 所以第一步肯定不是
		if (declaredEventType.isAssignableFrom(eventType)) {
			return true;
		}
		//明显走该条件
		else if (PayloadApplicationEvent.class.isAssignableFrom(eventType.getRawClass())) {
			ResolvableType payloadType = eventType.as(PayloadApplicationEvent.class).getGeneric();
			if (declaredEventType.isAssignableFrom(payloadType)) {
				return true;
			}
		}
	}
	return eventType.hasUnresolvableGenerics();
}

@EventListener生成的ApplicationListenerApplicationListenerMethodAdapter. 其处理方法为

  1. 解析出监听方法参数。
  2. 如果没有参数或者不满足condition , 不处理事件
  3. @EventListenner注解的事件类型大于方法参数中声明的事件类型

public void processEvent(ApplicationEvent event) {
    //解析出监听方法需要的参数
	Object[] args = resolveArguments(event);
	//如果没有参数或者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");
		}
	}
}

@Nullable
protected Object[] resolveArguments(ApplicationEvent event) {
    //获取event的对应的 ResolvableType。对应实现了applicationEvent的事件,就是事件类本身的class信息。
	ResolvableType declaredEventType = getResolvableType(event);
    	//如果未获取到event的 resolvableType,直接返回null
	if (declaredEventType == null) {
		return null;
	}
	//如果监听方法没有参数,则直接返回一个object[0]
	if (this.method.getParameterCount() == 0) {
		return new Object[0];
	}
	//获取 ResolvableType 的class 。 
	Class<?> declaredEventClass = declaredEventType.toClass();
	//如果不是 ApplicationEvent 并且event是 PayloadApplicationEvent。
	if (!ApplicationEvent.class.isAssignableFrom(declaredEventClass) &&
			event instanceof PayloadApplicationEvent) {
		Object payload = ((PayloadApplicationEvent<?>) event).getPayload();
		//判断payLoad是否是改生命对象的
		if (declaredEventClass.isInstance(payload)) {
			return new Object[] {payload};
		}
	}
	return new Object[] {event};
}


@Nullable
private ResolvableType getResolvableType(ApplicationEvent event) {
	ResolvableType payloadType = null;
	if (event instanceof PayloadApplicationEvent) {
		PayloadApplicationEvent<?> payloadEvent = (PayloadApplicationEvent<?>) event;
		ResolvableType eventType = payloadEvent.getResolvableType();
		if (eventType != null) {
			payloadType = eventType.as(PayloadApplicationEvent.class).getGeneric();
		}
	}
	for (ResolvableType declaredEventType : this.declaredEventTypes) {
		Class<?> eventClass = declaredEventType.toClass();
		if (!ApplicationEvent.class.isAssignableFrom(eventClass) &&
				payloadType != null && declaredEventType.isAssignableFrom(payloadType)) {
			return declaredEventType;
		}
		//对应applicationEvent, 直接判断 是不是 ApplicationListenerMethodAdapter 能处理event的实例  
		if (eventClass.isInstance(event)) {
			return declaredEventType;
		}
	}
	return null;
}

很好奇 为什么不直接用class进行事件和参数的比较,非要用ResolvableType来比较

ResolvableType的用途

猜你喜欢

转载自juejin.im/post/7114979331809476638