Skip to content

Commit 6183f06

Browse files
committed
Cache DependencyDescriptor per autowired constructor argument
Aligned with shortcut handling in AutowiredAnnotationBeanPostProcessor. Includes minor MethodInvoker optimization for pre-resolved targetClass. Closes gh-30883
1 parent a34f9fa commit 6183f06

File tree

11 files changed

+310
-115
lines changed

11 files changed

+310
-115
lines changed

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

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ protected void inject(Object bean, @Nullable String beanName, @Nullable Property
705705
private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
706706
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
707707
desc.setContainingClass(bean.getClass());
708-
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
708+
Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
709709
Assert.state(beanFactory != null, "No BeanFactory available");
710710
TypeConverter typeConverter = beanFactory.getTypeConverter();
711711
Object value;
@@ -724,8 +724,7 @@ private Object resolveFieldValue(Field field, Object bean, @Nullable String bean
724724
String autowiredBeanName = autowiredBeanNames.iterator().next();
725725
if (beanFactory.containsBean(autowiredBeanName) &&
726726
beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
727-
cachedFieldValue = new ShortcutDependencyDescriptor(
728-
desc, autowiredBeanName, field.getType());
727+
cachedFieldValue = new ShortcutDependencyDescriptor(desc, autowiredBeanName);
729728
}
730729
}
731730
this.cachedFieldValue = cachedFieldValue;
@@ -805,7 +804,7 @@ private Object[] resolveMethodArguments(Method method, Object bean, @Nullable St
805804
int argumentCount = method.getParameterCount();
806805
Object[] arguments = new Object[argumentCount];
807806
DependencyDescriptor[] descriptors = new DependencyDescriptor[argumentCount];
808-
Set<String> autowiredBeans = new LinkedHashSet<>(argumentCount);
807+
Set<String> autowiredBeanNames = new LinkedHashSet<>(argumentCount * 2);
809808
Assert.state(beanFactory != null, "No BeanFactory available");
810809
TypeConverter typeConverter = beanFactory.getTypeConverter();
811810
for (int i = 0; i < arguments.length; i++) {
@@ -814,7 +813,7 @@ private Object[] resolveMethodArguments(Method method, Object bean, @Nullable St
814813
currDesc.setContainingClass(bean.getClass());
815814
descriptors[i] = currDesc;
816815
try {
817-
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeans, typeConverter);
816+
Object arg = beanFactory.resolveDependency(currDesc, beanName, autowiredBeanNames, typeConverter);
818817
if (arg == null && !this.required) {
819818
arguments = null;
820819
break;
@@ -829,16 +828,16 @@ private Object[] resolveMethodArguments(Method method, Object bean, @Nullable St
829828
if (!this.cached) {
830829
if (arguments != null) {
831830
DependencyDescriptor[] cachedMethodArguments = Arrays.copyOf(descriptors, argumentCount);
832-
registerDependentBeans(beanName, autowiredBeans);
833-
if (autowiredBeans.size() == argumentCount) {
834-
Iterator<String> it = autowiredBeans.iterator();
831+
registerDependentBeans(beanName, autowiredBeanNames);
832+
if (autowiredBeanNames.size() == argumentCount) {
833+
Iterator<String> it = autowiredBeanNames.iterator();
835834
Class<?>[] paramTypes = method.getParameterTypes();
836835
for (int i = 0; i < paramTypes.length; i++) {
837836
String autowiredBeanName = it.next();
838837
if (arguments[i] != null && beanFactory.containsBean(autowiredBeanName) &&
839838
beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
840839
cachedMethodArguments[i] = new ShortcutDependencyDescriptor(
841-
descriptors[i], autowiredBeanName, paramTypes[i]);
840+
descriptors[i], autowiredBeanName);
842841
}
843842
}
844843
}
@@ -864,17 +863,14 @@ private static class ShortcutDependencyDescriptor extends DependencyDescriptor {
864863

865864
private final String shortcut;
866865

867-
private final Class<?> requiredType;
868-
869-
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut, Class<?> requiredType) {
866+
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut) {
870867
super(original);
871868
this.shortcut = shortcut;
872-
this.requiredType = requiredType;
873869
}
874870

875871
@Override
876872
public Object resolveShortcut(BeanFactory beanFactory) {
877-
return beanFactory.getBean(this.shortcut, this.requiredType);
873+
return beanFactory.getBean(this.shortcut, getDependencyType());
878874
}
879875
}
880876

spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredElementResolver.java

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 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.
@@ -62,20 +62,14 @@ static class ShortcutDependencyDescriptor extends DependencyDescriptor {
6262

6363
private final String shortcut;
6464

65-
private final Class<?> requiredType;
66-
67-
68-
public ShortcutDependencyDescriptor(DependencyDescriptor original,
69-
String shortcut, Class<?> requiredType) {
65+
public ShortcutDependencyDescriptor(DependencyDescriptor original, String shortcut) {
7066
super(original);
7167
this.shortcut = shortcut;
72-
this.requiredType = requiredType;
7368
}
7469

75-
7670
@Override
7771
public Object resolveShortcut(BeanFactory beanFactory) {
78-
return beanFactory.getBean(this.shortcut, this.requiredType);
72+
return beanFactory.getBean(this.shortcut, getDependencyType());
7973
}
8074
}
8175

spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredFieldValueResolver.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 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.
@@ -179,8 +179,7 @@ private Object resolveValue(RegisteredBean registeredBean, Field field) {
179179
DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required);
180180
descriptor.setContainingClass(beanClass);
181181
if (this.shortcut != null) {
182-
descriptor = new ShortcutDependencyDescriptor(descriptor, this.shortcut,
183-
field.getType());
182+
descriptor = new ShortcutDependencyDescriptor(descriptor, this.shortcut);
184183
}
185184
Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
186185
TypeConverter typeConverter = beanFactory.getTypeConverter();

spring-beans/src/main/java/org/springframework/beans/factory/aot/AutowiredMethodArgumentsResolver.java

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-2023 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.
@@ -76,18 +76,16 @@ private AutowiredMethodArgumentsResolver(String methodName, Class<?>[] parameter
7676
this.shortcuts = shortcuts;
7777
}
7878

79+
7980
/**
8081
* Create a new {@link AutowiredMethodArgumentsResolver} for the specified
8182
* method where injection is optional.
8283
* @param methodName the method name
8384
* @param parameterTypes the factory method parameter types
8485
* @return a new {@link AutowiredFieldValueResolver} instance
8586
*/
86-
public static AutowiredMethodArgumentsResolver forMethod(String methodName,
87-
Class<?>... parameterTypes) {
88-
89-
return new AutowiredMethodArgumentsResolver(methodName, parameterTypes, false,
90-
null);
87+
public static AutowiredMethodArgumentsResolver forMethod(String methodName, Class<?>... parameterTypes) {
88+
return new AutowiredMethodArgumentsResolver(methodName, parameterTypes, false, null);
9189
}
9290

9391
/**
@@ -97,11 +95,8 @@ public static AutowiredMethodArgumentsResolver forMethod(String methodName,
9795
* @param parameterTypes the factory method parameter types
9896
* @return a new {@link AutowiredFieldValueResolver} instance
9997
*/
100-
public static AutowiredMethodArgumentsResolver forRequiredMethod(String methodName,
101-
Class<?>... parameterTypes) {
102-
103-
return new AutowiredMethodArgumentsResolver(methodName, parameterTypes, true,
104-
null);
98+
public static AutowiredMethodArgumentsResolver forRequiredMethod(String methodName, Class<?>... parameterTypes) {
99+
return new AutowiredMethodArgumentsResolver(methodName, parameterTypes, true, null);
105100
}
106101

107102
/**
@@ -113,8 +108,7 @@ public static AutowiredMethodArgumentsResolver forRequiredMethod(String methodNa
113108
* the shortcuts
114109
*/
115110
public AutowiredMethodArgumentsResolver withShortcut(String... beanNames) {
116-
return new AutowiredMethodArgumentsResolver(this.methodName, this.parameterTypes,
117-
this.required, beanNames);
111+
return new AutowiredMethodArgumentsResolver(this.methodName, this.parameterTypes, this.required, beanNames);
118112
}
119113

120114
/**
@@ -123,9 +117,7 @@ public AutowiredMethodArgumentsResolver withShortcut(String... beanNames) {
123117
* @param registeredBean the registered bean
124118
* @param action the action to execute with the resolved method arguments
125119
*/
126-
public void resolve(RegisteredBean registeredBean,
127-
ThrowingConsumer<AutowiredArguments> action) {
128-
120+
public void resolve(RegisteredBean registeredBean, ThrowingConsumer<AutowiredArguments> action) {
129121
Assert.notNull(registeredBean, "'registeredBean' must not be null");
130122
Assert.notNull(action, "'action' must not be null");
131123
AutowiredArguments resolved = resolve(registeredBean);
@@ -177,25 +169,22 @@ private AutowiredArguments resolveArguments(RegisteredBean registeredBean,
177169
TypeConverter typeConverter = beanFactory.getTypeConverter();
178170
for (int i = 0; i < argumentCount; i++) {
179171
MethodParameter parameter = new MethodParameter(method, i);
180-
DependencyDescriptor descriptor = new DependencyDescriptor(parameter,
181-
this.required);
172+
DependencyDescriptor descriptor = new DependencyDescriptor(parameter, this.required);
182173
descriptor.setContainingClass(beanClass);
183-
String shortcut = (this.shortcuts != null) ? this.shortcuts[i] : null;
174+
String shortcut = (this.shortcuts != null ? this.shortcuts[i] : null);
184175
if (shortcut != null) {
185-
descriptor = new ShortcutDependencyDescriptor(descriptor, shortcut,
186-
parameter.getParameterType());
176+
descriptor = new ShortcutDependencyDescriptor(descriptor, shortcut);
187177
}
188178
try {
189-
Object argument = autowireCapableBeanFactory.resolveDependency(descriptor,
190-
beanName, autowiredBeanNames, typeConverter);
179+
Object argument = autowireCapableBeanFactory.resolveDependency(
180+
descriptor, beanName, autowiredBeanNames, typeConverter);
191181
if (argument == null && !this.required) {
192182
return null;
193183
}
194184
arguments[i] = argument;
195185
}
196186
catch (BeansException ex) {
197-
throw new UnsatisfiedDependencyException(null, beanName,
198-
new InjectionPoint(parameter), ex);
187+
throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(parameter), ex);
199188
}
200189
}
201190
registerDependentBeans(beanFactory, beanName, autowiredBeanNames);

spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanInstanceSupplier.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,18 +248,18 @@ private AutowiredArguments resolveArguments(RegisteredBean registeredBean, Execu
248248
() -> "'shortcuts' must contain " + resolved.length + " elements");
249249

250250
ConstructorArgumentValues argumentValues = resolveArgumentValues(registeredBean);
251-
Set<String> autowiredBeans = new LinkedHashSet<>(resolved.length);
251+
Set<String> autowiredBeanNames = new LinkedHashSet<>(resolved.length * 2);
252252
for (int i = startIndex; i < parameterCount; i++) {
253253
MethodParameter parameter = getMethodParameter(executable, i);
254254
DependencyDescriptor descriptor = new DependencyDescriptor(parameter, true);
255255
String shortcut = (this.shortcuts != null ? this.shortcuts[i - startIndex] : null);
256256
if (shortcut != null) {
257-
descriptor = new ShortcutDependencyDescriptor(descriptor, shortcut, registeredBean.getBeanClass());
257+
descriptor = new ShortcutDependencyDescriptor(descriptor, shortcut);
258258
}
259259
ValueHolder argumentValue = argumentValues.getIndexedArgumentValue(i, null);
260-
resolved[i - startIndex] = resolveArgument(registeredBean, descriptor, argumentValue, autowiredBeans);
260+
resolved[i - startIndex] = resolveArgument(registeredBean, descriptor, argumentValue, autowiredBeanNames);
261261
}
262-
registerDependentBeans(registeredBean.getBeanFactory(), registeredBean.getBeanName(), autowiredBeans);
262+
registerDependentBeans(registeredBean.getBeanFactory(), registeredBean.getBeanName(), autowiredBeanNames);
263263

264264
return AutowiredArguments.of(resolved);
265265
}
@@ -302,7 +302,7 @@ private ValueHolder resolveArgumentValue(BeanDefinitionValueResolver resolver, V
302302

303303
@Nullable
304304
private Object resolveArgument(RegisteredBean registeredBean, DependencyDescriptor descriptor,
305-
@Nullable ValueHolder argumentValue, Set<String> autowiredBeans) {
305+
@Nullable ValueHolder argumentValue, Set<String> autowiredBeanNames) {
306306

307307
TypeConverter typeConverter = registeredBean.getBeanFactory().getTypeConverter();
308308
if (argumentValue != null) {
@@ -311,7 +311,7 @@ private Object resolveArgument(RegisteredBean registeredBean, DependencyDescript
311311
descriptor.getDependencyType(), descriptor.getMethodParameter()));
312312
}
313313
try {
314-
return registeredBean.resolveAutowiredArgument(descriptor, typeConverter, autowiredBeans);
314+
return registeredBean.resolveAutowiredArgument(descriptor, typeConverter, autowiredBeanNames);
315315
}
316316
catch (BeansException ex) {
317317
throw new UnsatisfiedDependencyException(null, registeredBean.getBeanName(), descriptor, ex);

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1483,8 +1483,8 @@ protected void autowireByType(
14831483
converter = bw;
14841484
}
14851485

1486-
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
14871486
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
1487+
Set<String> autowiredBeanNames = new LinkedHashSet<>(propertyNames.length * 2);
14881488
for (String propertyName : propertyNames) {
14891489
try {
14901490
PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);

spring-beans/src/main/java/org/springframework/beans/factory/support/BeanDefinitionValueResolver.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ else if (value instanceof BeanDefinition bd) {
153153
(name, mbd) -> resolveInnerBeanValue(argName, name, mbd));
154154
}
155155
else if (value instanceof DependencyDescriptor dependencyDescriptor) {
156-
Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
156+
Set<String> autowiredBeanNames = new LinkedHashSet<>(2);
157157
Object result = this.beanFactory.resolveDependency(
158158
dependencyDescriptor, this.beanName, autowiredBeanNames, this.typeConverter);
159159
for (String autowiredBeanName : autowiredBeanNames) {

0 commit comments

Comments
 (0)