001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.context.event; 018 019import java.util.Map; 020 021import org.springframework.aop.support.AopUtils; 022import org.springframework.context.ApplicationEvent; 023import org.springframework.context.ApplicationListener; 024import org.springframework.core.Ordered; 025import org.springframework.core.ResolvableType; 026import org.springframework.lang.Nullable; 027import org.springframework.util.Assert; 028import org.springframework.util.ConcurrentReferenceHashMap; 029 030/** 031 * {@link GenericApplicationListener} adapter that determines supported event types 032 * through introspecting the generically declared type of the target listener. 033 * 034 * @author Juergen Hoeller 035 * @author Stephane Nicoll 036 * @since 3.0 037 * @see org.springframework.context.ApplicationListener#onApplicationEvent 038 */ 039public class GenericApplicationListenerAdapter implements GenericApplicationListener, SmartApplicationListener { 040 041 private static final Map<Class<?>, ResolvableType> eventTypeCache = new ConcurrentReferenceHashMap<>(); 042 043 044 private final ApplicationListener<ApplicationEvent> delegate; 045 046 @Nullable 047 private final ResolvableType declaredEventType; 048 049 050 /** 051 * Create a new GenericApplicationListener for the given delegate. 052 * @param delegate the delegate listener to be invoked 053 */ 054 @SuppressWarnings("unchecked") 055 public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) { 056 Assert.notNull(delegate, "Delegate listener must not be null"); 057 this.delegate = (ApplicationListener<ApplicationEvent>) delegate; 058 this.declaredEventType = resolveDeclaredEventType(this.delegate); 059 } 060 061 062 @Override 063 public void onApplicationEvent(ApplicationEvent event) { 064 this.delegate.onApplicationEvent(event); 065 } 066 067 @Override 068 @SuppressWarnings("unchecked") 069 public boolean supportsEventType(ResolvableType eventType) { 070 if (this.delegate instanceof SmartApplicationListener) { 071 Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve(); 072 return (eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass)); 073 } 074 else { 075 return (this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType)); 076 } 077 } 078 079 @Override 080 public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) { 081 return supportsEventType(ResolvableType.forClass(eventType)); 082 } 083 084 @Override 085 public boolean supportsSourceType(@Nullable Class<?> sourceType) { 086 return !(this.delegate instanceof SmartApplicationListener) || 087 ((SmartApplicationListener) this.delegate).supportsSourceType(sourceType); 088 } 089 090 @Override 091 public int getOrder() { 092 return (this.delegate instanceof Ordered ? ((Ordered) this.delegate).getOrder() : Ordered.LOWEST_PRECEDENCE); 093 } 094 095 096 @Nullable 097 private static ResolvableType resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener) { 098 ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass()); 099 if (declaredEventType == null || declaredEventType.isAssignableFrom(ApplicationEvent.class)) { 100 Class<?> targetClass = AopUtils.getTargetClass(listener); 101 if (targetClass != listener.getClass()) { 102 declaredEventType = resolveDeclaredEventType(targetClass); 103 } 104 } 105 return declaredEventType; 106 } 107 108 @Nullable 109 static ResolvableType resolveDeclaredEventType(Class<?> listenerType) { 110 ResolvableType eventType = eventTypeCache.get(listenerType); 111 if (eventType == null) { 112 eventType = ResolvableType.forClass(listenerType).as(ApplicationListener.class).getGeneric(); 113 eventTypeCache.put(listenerType, eventType); 114 } 115 return (eventType != ResolvableType.NONE ? eventType : null); 116 } 117 118}