Skip to content

Commit c0ddaae

Browse files
committed
Shared empty InjectionMetadata/LifecycleMetadata instance
Closes gh-22570
1 parent 62c9237 commit c0ddaae

File tree

5 files changed

+72
-10
lines changed

5 files changed

+72
-10
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz
443443

444444
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
445445
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
446-
return new InjectionMetadata(clazz, Collections.emptyList());
446+
return InjectionMetadata.EMPTY;
447447
}
448448

449449
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
@@ -496,7 +496,7 @@ private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
496496
}
497497
while (targetClass != null && targetClass != Object.class);
498498

499-
return new InjectionMetadata(clazz, elements);
499+
return InjectionMetadata.forElements(elements, clazz);
500500
}
501501

502502
@Nullable

spring-beans/src/main/java/org/springframework/beans/factory/annotation/InitDestroyAnnotationBeanPostProcessor.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,24 @@
8080
public class InitDestroyAnnotationBeanPostProcessor
8181
implements DestructionAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, Serializable {
8282

83+
private final transient LifecycleMetadata emptyLifecycleMetadata =
84+
new LifecycleMetadata(Object.class, Collections.emptyList(), Collections.emptyList()) {
85+
@Override
86+
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
87+
}
88+
@Override
89+
public void invokeInitMethods(Object target, String beanName) {
90+
}
91+
@Override
92+
public void invokeDestroyMethods(Object target, String beanName) {
93+
}
94+
@Override
95+
public boolean hasDestroyMethods() {
96+
return false;
97+
}
98+
};
99+
100+
83101
protected transient Log logger = LogFactory.getLog(getClass());
84102

85103
@Nullable
@@ -200,7 +218,7 @@ private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
200218

201219
private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
202220
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
203-
return new LifecycleMetadata(clazz, Collections.emptyList(), Collections.emptyList());
221+
return this.emptyLifecycleMetadata;
204222
}
205223

206224
List<LifecycleElement> initMethods = new ArrayList<>();
@@ -233,7 +251,8 @@ private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
233251
}
234252
while (targetClass != null && targetClass != Object.class);
235253

236-
return new LifecycleMetadata(clazz, initMethods, destroyMethods);
254+
return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
255+
new LifecycleMetadata(clazz, initMethods, destroyMethods));
237256
}
238257

239258

spring-beans/src/main/java/org/springframework/beans/factory/annotation/InjectionMetadata.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
2222
import java.lang.reflect.Member;
2323
import java.lang.reflect.Method;
2424
import java.util.Collection;
25+
import java.util.Collections;
2526
import java.util.LinkedHashSet;
2627
import java.util.Set;
2728

@@ -47,6 +48,23 @@
4748
*/
4849
public class InjectionMetadata {
4950

51+
/**
52+
* An empty {@code InjectionMetadata} instance with no-op callbacks.
53+
* @since 5.2
54+
*/
55+
public static final InjectionMetadata EMPTY = new InjectionMetadata(Object.class, Collections.emptyList()) {
56+
@Override
57+
public void checkConfigMembers(RootBeanDefinition beanDefinition) {
58+
}
59+
@Override
60+
public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) {
61+
}
62+
@Override
63+
public void clear(@Nullable PropertyValues pvs) {
64+
}
65+
};
66+
67+
5068
private static final Log logger = LogFactory.getLog(InjectionMetadata.class);
5169

5270
private final Class<?> targetClass;
@@ -57,6 +75,14 @@ public class InjectionMetadata {
5775
private volatile Set<InjectedElement> checkedElements;
5876

5977

78+
/**
79+
* Create a new {@code InjectionMetadata instance}.
80+
* <p>Preferably use {@link #forElements} for reusing the {@link #EMPTY}
81+
* instance in case of no elements.
82+
* @param targetClass the target class
83+
* @param elements the associated elements to inject
84+
* @see #forElements
85+
*/
6086
public InjectionMetadata(Class<?> targetClass, Collection<InjectedElement> elements) {
6187
this.targetClass = targetClass;
6288
this.injectedElements = elements;
@@ -108,6 +134,24 @@ public void clear(@Nullable PropertyValues pvs) {
108134
}
109135

110136

137+
/**
138+
* Return an {@code InjectionMetadata} instance, possibly for empty elements.
139+
* @param elements the elements to inject (possibly empty)
140+
* @param clazz the target class
141+
* @return a new {@code InjectionMetadata} instance,
142+
* or {@link #EMPTY} in case of no elements
143+
* @since 5.2
144+
*/
145+
public static InjectionMetadata forElements(Collection<InjectedElement> elements, Class<?> clazz) {
146+
return (elements.isEmpty() ? InjectionMetadata.EMPTY : new InjectionMetadata(clazz, elements));
147+
}
148+
149+
/**
150+
* Check whether the given injection metadata needs to be refreshed.
151+
* @param metadata the existing metadata instance
152+
* @param clazz the current target class
153+
* @return {@code true} indicating a refresh, {@code false} otherwise
154+
*/
111155
public static boolean needsRefresh(@Nullable InjectionMetadata metadata, Class<?> clazz) {
112156
return (metadata == null || metadata.targetClass != clazz);
113157
}

spring-context/src/main/java/org/springframework/context/annotation/CommonAnnotationBeanPostProcessor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ private InjectionMetadata findResourceMetadata(String beanName, final Class<?> c
369369

370370
private InjectionMetadata buildResourceMetadata(final Class<?> clazz) {
371371
if (!AnnotationUtils.isCandidateClass(clazz, resourceAnnotationTypes)) {
372-
return new InjectionMetadata(clazz, Collections.emptyList());
372+
return InjectionMetadata.EMPTY;
373373
}
374374

375375
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
@@ -448,7 +448,7 @@ else if (bridgedMethod.isAnnotationPresent(Resource.class)) {
448448
}
449449
while (targetClass != null && targetClass != Object.class);
450450

451-
return new InjectionMetadata(clazz, elements);
451+
return InjectionMetadata.forElements(elements, clazz);
452452
}
453453

454454
/**

spring-orm/src/main/java/org/springframework/orm/jpa/support/PersistenceAnnotationBeanPostProcessor.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import java.lang.reflect.Modifier;
2525
import java.util.ArrayList;
2626
import java.util.Arrays;
27-
import java.util.Collections;
2827
import java.util.LinkedList;
2928
import java.util.List;
3029
import java.util.Map;
@@ -416,7 +415,7 @@ private InjectionMetadata findPersistenceMetadata(String beanName, final Class<?
416415

417416
private InjectionMetadata buildPersistenceMetadata(final Class<?> clazz) {
418417
if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(PersistenceContext.class, PersistenceUnit.class))) {
419-
return new InjectionMetadata(clazz, Collections.emptyList());
418+
return InjectionMetadata.EMPTY;
420419
}
421420

422421
List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
@@ -459,7 +458,7 @@ private InjectionMetadata buildPersistenceMetadata(final Class<?> clazz) {
459458
}
460459
while (targetClass != null && targetClass != Object.class);
461460

462-
return new InjectionMetadata(clazz, elements);
461+
return InjectionMetadata.forElements(elements, clazz);
463462
}
464463

465464
/**

0 commit comments

Comments
 (0)