19
19
import java .lang .reflect .Modifier ;
20
20
import java .util .ArrayList ;
21
21
import java .util .Collection ;
22
+ import java .util .Comparator ;
22
23
import java .util .LinkedHashSet ;
23
24
import java .util .List ;
24
25
import java .util .Map ;
28
29
29
30
import org .springframework .aop .framework .AopProxyUtils ;
30
31
import org .springframework .beans .factory .BeanFactory ;
31
- import org .springframework .beans .factory .ListableBeanFactory ;
32
32
import org .springframework .beans .factory .config .BeanDefinition ;
33
33
import org .springframework .beans .factory .config .ConfigurableBeanFactory ;
34
- import org .springframework .beans .factory .support . BeanDefinitionRegistry ;
34
+ import org .springframework .beans .factory .config . ConfigurableListableBeanFactory ;
35
35
import org .springframework .core .ResolvableType ;
36
36
import org .springframework .core .annotation .AnnotationAwareOrderComparator ;
37
37
import org .springframework .lang .Nullable ;
@@ -56,7 +56,6 @@ class EntityCallbackDiscoverer {
56
56
private final Map <Class <?>, ResolvableType > entityTypeCache = new ConcurrentReferenceHashMap <>(64 );
57
57
58
58
@ Nullable private ClassLoader beanClassLoader ;
59
- @ Nullable private BeanFactory beanFactory ;
60
59
61
60
private Object retrievalMutex = this .defaultRetriever ;
62
61
@@ -104,12 +103,13 @@ void removeEntityCallback(EntityCallback<?> callback) {
104
103
* Return a {@link Collection} of all {@link EntityCallback}s matching the given entity type. Non-matching callbacks
105
104
* get excluded early.
106
105
*
107
- * @param entity the entity to be called back for. Allows for excluding non-matching callbacks early, based on
108
- * cached matching information.
106
+ * @param entity the entity to be called back for. Allows for excluding non-matching callbacks early, based on cached
107
+ * matching information.
109
108
* @param callbackType the source callback type.
110
109
* @return a {@link Collection} of {@link EntityCallback}s.
111
110
* @see EntityCallback
112
111
*/
112
+ @ SuppressWarnings ({ "unchecked" , "rawtypes" })
113
113
<T extends S , S > Collection <EntityCallback <S >> getEntityCallbacks (Class <T > entity , ResolvableType callbackType ) {
114
114
115
115
Class <?> sourceType = entity ;
@@ -121,7 +121,7 @@ <T extends S, S> Collection<EntityCallback<S>> getEntityCallbacks(Class<T> entit
121
121
return (Collection ) retriever .getEntityCallbacks ();
122
122
}
123
123
124
- if (this .beanClassLoader == null || ClassUtils .isCacheSafe (entity . getClass () , this .beanClassLoader )
124
+ if (this .beanClassLoader == null || ClassUtils .isCacheSafe (entity , this .beanClassLoader )
125
125
&& (sourceType == null || ClassUtils .isCacheSafe (sourceType , this .beanClassLoader ))) {
126
126
127
127
// Fully synchronized building and caching of a CallbackRetriever
@@ -163,8 +163,8 @@ ResolvableType resolveDeclaredEntityType(Class<?> callbackType) {
163
163
* @param retriever the {@link CallbackRetriever}, if supposed to populate one (for caching purposes)
164
164
* @return the pre-filtered list of entity callbacks for the given entity and callback type.
165
165
*/
166
- private Collection <EntityCallback <?>> retrieveEntityCallbacks (ResolvableType entityType ,
167
- ResolvableType callbackType , @ Nullable CallbackRetriever retriever ) {
166
+ private Collection <EntityCallback <?>> retrieveEntityCallbacks (ResolvableType entityType , ResolvableType callbackType ,
167
+ @ Nullable CallbackRetriever retriever ) {
168
168
169
169
List <EntityCallback <?>> allCallbacks = new ArrayList <>();
170
170
Set <EntityCallback <?>> callbacks ;
@@ -198,16 +198,14 @@ private Collection<EntityCallback<?>> retrieveEntityCallbacks(ResolvableType ent
198
198
}
199
199
200
200
/**
201
- * Set the {@link BeanFactory} and optionally {@link #setBeanClassLoader(ClassLoader) class loader} if not set.
202
- * Pre-loads {@link EntityCallback} beans by scanning the {@link BeanFactory}.
201
+ * Set the {@link BeanFactory} and optionally class loader if not set. Pre-loads {@link EntityCallback} beans by
202
+ * scanning the {@link BeanFactory}.
203
203
*
204
204
* @param beanFactory must not be {@literal null}.
205
205
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(BeanFactory)
206
206
*/
207
207
public void setBeanFactory (BeanFactory beanFactory ) {
208
208
209
- this .beanFactory = beanFactory ;
210
-
211
209
if (beanFactory instanceof ConfigurableBeanFactory cbf ) {
212
210
213
211
if (this .beanClassLoader == null ) {
@@ -228,10 +226,8 @@ static Method lookupCallbackMethod(Class<?> callbackType, Class<?> entityType, O
228
226
229
227
ReflectionUtils .doWithMethods (callbackType , methods ::add , method -> {
230
228
231
- if (!Modifier .isPublic (method .getModifiers ())
232
- || method .getParameterCount () != args .length + 1
233
- || method .isBridge ()
234
- || ReflectionUtils .isObjectMethod (method )) {
229
+ if (!Modifier .isPublic (method .getModifiers ()) || method .getParameterCount () != args .length + 1
230
+ || method .isBridge () || ReflectionUtils .isObjectMethod (method )) {
235
231
return false ;
236
232
}
237
233
@@ -242,9 +238,8 @@ static Method lookupCallbackMethod(Class<?> callbackType, Class<?> entityType, O
242
238
return methods .iterator ().next ();
243
239
}
244
240
245
- throw new IllegalStateException (
246
- "%s does not define a callback method accepting %s and %s additional arguments" .formatted (
247
- ClassUtils .getShortName (callbackType ), ClassUtils .getShortName (entityType ), args .length ));
241
+ throw new IllegalStateException ("%s does not define a callback method accepting %s and %s additional arguments"
242
+ .formatted (ClassUtils .getShortName (callbackType ), ClassUtils .getShortName (entityType ), args .length ));
248
243
}
249
244
250
245
static <T > BiFunction <EntityCallback <T >, T , Object > computeCallbackInvokerFunction (EntityCallback <T > callback ,
@@ -267,10 +262,10 @@ static <T> BiFunction<EntityCallback<T>, T, Object> computeCallbackInvokerFuncti
267
262
* Filter a callback early through checking its generically declared entity type before trying to instantiate it.
268
263
* <p>
269
264
* If this method returns {@literal true} for a given callback as a first pass, the callback instance will get
270
- * retrieved and fully evaluated through a {@link #supportsEvent(EntityCallback, ResolvableType, ResolvableType)}
271
- * call afterwards.
265
+ * retrieved and fully evaluated through a {@link #supportsEvent(EntityCallback, ResolvableType, ResolvableType)} call
266
+ * afterwards.
272
267
*
273
- * @param callback the callback's type as determined by the BeanFactory.
268
+ * @param callbackType the callback's type as determined by the BeanFactory.
274
269
* @param entityType the entity type to check.
275
270
* @return whether the given callback should be included in the candidates for the given callback type.
276
271
*/
@@ -286,11 +281,9 @@ static boolean supportsEvent(ResolvableType callbackType, ResolvableType entityT
286
281
* @param callbackType the source type to check against.
287
282
* @return whether the given callback should be included in the candidates for the given callback type.
288
283
*/
289
- static boolean supportsEvent (EntityCallback <?> callback , ResolvableType entityType ,
290
- ResolvableType callbackType ) {
284
+ static boolean supportsEvent (EntityCallback <?> callback , ResolvableType entityType , ResolvableType callbackType ) {
291
285
292
- return callback instanceof EntityCallbackAdapter <?> provider
293
- ? provider .supports (callbackType , entityType )
286
+ return callback instanceof EntityCallbackAdapter <?> provider ? provider .supports (callbackType , entityType )
294
287
: callbackType .isInstance (callback ) && supportsEvent (ResolvableType .forInstance (callback ), entityType );
295
288
}
296
289
@@ -310,13 +303,11 @@ void discoverEntityCallbacks(BeanFactory beanFactory) {
310
303
311
304
// We need both a ListableBeanFactory and BeanDefinitionRegistry here for advanced inspection.
312
305
// If we don't get that, use simple inspection.
313
- if (!(beanFactory instanceof ListableBeanFactory && beanFactory instanceof BeanDefinitionRegistry )) {
306
+ if (!(beanFactory instanceof ConfigurableListableBeanFactory bf )) {
314
307
beanFactory .getBeanProvider (EntityCallback .class ).stream ().forEach (entityCallbacks ::add );
315
308
return ;
316
309
}
317
310
318
- var bf = (ListableBeanFactory & BeanDefinitionRegistry ) beanFactory ;
319
-
320
311
for (var beanName : bf .getBeanNamesForType (EntityCallback .class )) {
321
312
322
313
EntityCallback <?> bean = EntityCallback .class .cast (bf .getBean (beanName ));
@@ -328,7 +319,7 @@ void discoverEntityCallbacks(BeanFactory beanFactory) {
328
319
entityCallbacks .add (bean );
329
320
} else {
330
321
331
- BeanDefinition definition = bf .getBeanDefinition (beanName );
322
+ BeanDefinition definition = bf .getMergedBeanDefinition (beanName );
332
323
entityCallbacks .add (new EntityCallbackAdapter <>(bean , definition .getResolvableType ()));
333
324
}
334
325
}
@@ -340,8 +331,8 @@ void discoverEntityCallbacks(BeanFactory beanFactory) {
340
331
*
341
332
* @author Oliver Drotbohm
342
333
*/
343
- private static record EntityCallbackAdapter <T >(EntityCallback <T > delegate , ResolvableType type )
344
- implements EntityCallback <T > {
334
+ private record EntityCallbackAdapter <T > (EntityCallback <T > delegate ,
335
+ ResolvableType type ) implements EntityCallback <T > {
345
336
346
337
boolean supports (ResolvableType callbackType , ResolvableType entityType ) {
347
338
return callbackType .isInstance (delegate ) && supportsEvent (type , entityType );
@@ -351,15 +342,16 @@ boolean supports(ResolvableType callbackType, ResolvableType entityType) {
351
342
/**
352
343
* Cache key for {@link EntityCallback}, based on event type and source type.
353
344
*/
354
- private static record CallbackCacheKey (ResolvableType callbackType , @ Nullable Class <?> entityType )
355
- implements Comparable <CallbackCacheKey > {
345
+ private record CallbackCacheKey (ResolvableType callbackType ,
346
+ @ Nullable Class <?> entityType ) implements Comparable <CallbackCacheKey > {
347
+
348
+ private static final Comparator <CallbackCacheKey > COMPARATOR = Comparators .<CallbackCacheKey > nullsHigh () //
349
+ .thenComparing (it -> it .callbackType .toString ()) //
350
+ .thenComparing (it -> it .entityType .getName ());
356
351
357
352
@ Override
358
353
public int compareTo (CallbackCacheKey other ) {
359
-
360
- return Comparators .<CallbackCacheKey > nullsHigh ()
361
- .thenComparing (it -> callbackType .toString ())
362
- .thenComparing (it -> entityType .getName ()).compare (this , other );
354
+ return COMPARATOR .compare (this , other );
363
355
}
364
356
}
365
357
0 commit comments