• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TAKETODAY / today-infrastructure / 18154768944

01 Oct 2025 07:26AM UTC coverage: 81.882% (-0.005%) from 81.887%
18154768944

push

github

web-flow
Merge pull request #290 from TAKETODAY/dev/jspecify

jspecify

59788 of 78013 branches covered (76.64%)

Branch coverage included in aggregate %.

141239 of 167496 relevant lines covered (84.32%)

3.6 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.33
today-context/src/main/java/infra/context/event/GenericApplicationListenerAdapter.java
1
/*
2
 * Copyright 2017 - 2025 the original author or authors.
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see [https://www.gnu.org/licenses/]
16
 */
17

18
package infra.context.event;
19

20
import org.jspecify.annotations.Nullable;
21

22
import java.util.Map;
23

24
import infra.aop.support.AopUtils;
25
import infra.context.ApplicationEvent;
26
import infra.context.ApplicationListener;
27
import infra.core.Ordered;
28
import infra.core.ResolvableType;
29
import infra.lang.Assert;
30
import infra.util.ConcurrentReferenceHashMap;
31

32
/**
33
 * {@link GenericApplicationListener} adapter that determines supported event types
34
 * through introspecting the generically declared type of the target listener.
35
 *
36
 * @author Juergen Hoeller
37
 * @author Stephane Nicoll
38
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
39
 * @see ApplicationListener#onApplicationEvent
40
 * @since 4.0
41
 */
42
@SuppressWarnings("rawtypes")
43
public class GenericApplicationListenerAdapter implements GenericApplicationListener {
44

45
  private static final Map<Class<?>, ResolvableType> eventTypeCache = new ConcurrentReferenceHashMap<>();
5✔
46

47
  private final ApplicationListener delegate;
48

49
  @Nullable
50
  private final ResolvableType declaredEventType;
51

52
  /**
53
   * Create a new GenericApplicationListener for the given delegate.
54
   *
55
   * @param delegate the delegate listener to be invoked
56
   */
57
  public GenericApplicationListenerAdapter(ApplicationListener delegate) {
2✔
58
    Assert.notNull(delegate, "Delegate listener is required");
3✔
59
    this.delegate = delegate;
3✔
60
    this.declaredEventType = resolveDeclaredEventType(this.delegate);
5✔
61
  }
1✔
62

63
  @Override
64
  @SuppressWarnings("unchecked")
65
  public void onApplicationEvent(ApplicationEvent event) {
66
    this.delegate.onApplicationEvent(event);
4✔
67
  }
1✔
68

69
  @Override
70
  @SuppressWarnings("unchecked")
71
  public boolean supportsEventType(ResolvableType eventType) {
72
    if (this.delegate instanceof GenericApplicationListener) {
4!
73
      return ((GenericApplicationListener) this.delegate).supportsEventType(eventType);
×
74
    }
75
    else if (this.delegate instanceof SmartApplicationListener) {
4✔
76
      Class<? extends ApplicationEvent> eventClass = (Class<? extends ApplicationEvent>) eventType.resolve();
3✔
77
      return eventClass != null && ((SmartApplicationListener) this.delegate).supportsEventType(eventClass);
12!
78
    }
79
    else {
80
      return this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType);
12!
81
    }
82
  }
83

84
  @Override
85
  public boolean supportsSourceType(@Nullable Class<?> sourceType) {
86
    return !(this.delegate instanceof SmartApplicationListener)
9✔
87
            || ((SmartApplicationListener) this.delegate).supportsSourceType(sourceType);
5✔
88
  }
89

90
  @Override
91
  public int getOrder() {
92
    return this.delegate instanceof Ordered ? ((Ordered) this.delegate).getOrder() : LOWEST_PRECEDENCE;
×
93
  }
94

95
  @Override
96
  public String getListenerId() {
97
    return this.delegate instanceof SmartApplicationListener smart ? smart.getListenerId() : "";
×
98
  }
99

100
  @Nullable
101
  private static ResolvableType resolveDeclaredEventType(ApplicationListener<?> listener) {
102
    ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass());
4✔
103
    if (declaredEventType == null || declaredEventType.isAssignableFrom(ApplicationEvent.class)) {
6!
104
      Class<?> targetClass = AopUtils.getTargetClass(listener);
3✔
105
      if (targetClass != listener.getClass()) {
4✔
106
        declaredEventType = resolveDeclaredEventType(targetClass);
3✔
107
      }
108
    }
109
    return declaredEventType;
2✔
110
  }
111

112
  @Nullable
113
  static ResolvableType resolveDeclaredEventType(Class<?> listenerType) {
114
    ResolvableType eventType = eventTypeCache.get(listenerType);
5✔
115
    if (eventType == null) {
2✔
116
      eventType = ResolvableType.forClass(listenerType)
3✔
117
              .as(ApplicationListener.class)
3✔
118
              .getGeneric();
2✔
119
      eventTypeCache.put(listenerType, eventType);
5✔
120
    }
121
    return eventType != ResolvableType.NONE ? eventType : null;
6!
122
  }
123

124
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc