Skip to content

Commit 90c8751

Browse files
committed
Merge branch '6.2.x'
# Conflicts: # spring-context/src/main/java/org/springframework/context/aot/BeanFactoryInitializationAotContributions.java # spring-context/src/test/java/org/springframework/context/aot/ApplicationContextAotGeneratorTests.java # spring-orm/src/main/java/org/springframework/orm/hibernate5/HibernateQueryException.java
2 parents 04f3975 + b6aa689 commit 90c8751

File tree

14 files changed

+333
-144
lines changed

14 files changed

+333
-144
lines changed

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
import org.springframework.beans.factory.support.AbstractBeanDefinition;
5454
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
5555
import org.springframework.beans.factory.support.InstanceSupplier;
56+
import org.springframework.beans.factory.support.LookupOverride;
57+
import org.springframework.beans.factory.support.MethodOverride;
58+
import org.springframework.beans.factory.support.ReplaceOverride;
5659
import org.springframework.beans.factory.support.RootBeanDefinition;
5760
import org.springframework.javapoet.CodeBlock;
5861
import org.springframework.javapoet.CodeBlock.Builder;
@@ -145,6 +148,7 @@ CodeBlock generateCode(RootBeanDefinition beanDefinition) {
145148
addPropertyValues(code, beanDefinition);
146149
addAttributes(code, beanDefinition);
147150
addQualifiers(code, beanDefinition);
151+
addMethodOverrides(code, beanDefinition);
148152
return code.build();
149153
}
150154

@@ -274,6 +278,36 @@ private void addQualifiers(CodeBlock.Builder code, RootBeanDefinition beanDefini
274278
}
275279
}
276280

281+
private void addMethodOverrides(CodeBlock.Builder code, RootBeanDefinition beanDefinition) {
282+
if (beanDefinition.hasMethodOverrides()) {
283+
for (MethodOverride methodOverride : beanDefinition.getMethodOverrides().getOverrides()) {
284+
if (methodOverride instanceof LookupOverride lookupOverride) {
285+
Collection<CodeBlock> arguments = new ArrayList<>();
286+
arguments.add(CodeBlock.of("$S", lookupOverride.getMethodName()));
287+
arguments.add(CodeBlock.of("$S", lookupOverride.getBeanName()));
288+
code.addStatement("$L.getMethodOverrides().addOverride(new $T($L))", BEAN_DEFINITION_VARIABLE,
289+
LookupOverride.class, CodeBlock.join(arguments, ", "));
290+
}
291+
else if (methodOverride instanceof ReplaceOverride replaceOverride) {
292+
Collection<CodeBlock> arguments = new ArrayList<>();
293+
arguments.add(CodeBlock.of("$S", replaceOverride.getMethodName()));
294+
arguments.add(CodeBlock.of("$S", replaceOverride.getMethodReplacerBeanName()));
295+
List<String> typeIdentifiers = replaceOverride.getTypeIdentifiers();
296+
if (!typeIdentifiers.isEmpty()) {
297+
arguments.add(CodeBlock.of("java.util.List.of($S)",
298+
StringUtils.collectionToDelimitedString(typeIdentifiers, ", ")));
299+
}
300+
code.addStatement("$L.getMethodOverrides().addOverride(new $T($L))", BEAN_DEFINITION_VARIABLE,
301+
ReplaceOverride.class, CodeBlock.join(arguments, ", "));
302+
}
303+
else {
304+
throw new UnsupportedOperationException("Unexpected MethodOverride subclass: " +
305+
methodOverride.getClass().getName());
306+
}
307+
}
308+
}
309+
}
310+
277311
private CodeBlock generateValue(@Nullable String name, @Nullable Object value) {
278312
PropertyNamesStack.push(name);
279313
try {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.springframework.beans.factory.config.DependencyDescriptor;
4141
import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
4242
import org.springframework.beans.factory.support.BeanDefinitionValueResolver;
43+
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
4344
import org.springframework.beans.factory.support.InstanceSupplier;
4445
import org.springframework.beans.factory.support.RegisteredBean;
4546
import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -343,6 +344,11 @@ private ValueHolder resolveArgumentValue(BeanDefinitionValueResolver resolver, V
343344

344345
private Object instantiate(RegisteredBean registeredBean, Executable executable, @Nullable Object[] args) {
345346
if (executable instanceof Constructor<?> constructor) {
347+
if (registeredBean.getBeanFactory() instanceof DefaultListableBeanFactory dlbf &&
348+
registeredBean.getMergedBeanDefinition().hasMethodOverrides()) {
349+
return dlbf.getInstantiationStrategy().instantiate(registeredBean.getMergedBeanDefinition(),
350+
registeredBean.getBeanName(), registeredBean.getBeanFactory());
351+
}
346352
return BeanUtils.instantiateClass(constructor, args);
347353
}
348354
if (executable instanceof Method method) {

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ public interface BeanRegistrationAotContribution {
4141
* default code generation isn't suitable.
4242
* @param generationContext the generation context
4343
* @param codeFragments the existing code fragments
44-
* @return the code fragments to use, may be the original instance or a
45-
* wrapper
44+
* @return the code fragments to use, may be the original instance or a wrapper
4645
*/
4746
default BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments(
4847
GenerationContext generationContext, BeanRegistrationCodeFragments codeFragments) {
@@ -78,8 +77,7 @@ public BeanRegistrationCodeFragments customizeBeanRegistrationCodeFragments(
7877
return defaultCodeFragments.apply(codeFragments);
7978
}
8079
@Override
81-
public void applyTo(GenerationContext generationContext,
82-
BeanRegistrationCode beanRegistrationCode) {
80+
public void applyTo(GenerationContext generationContext, BeanRegistrationCode beanRegistrationCode) {
8381
}
8482
};
8583
}

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

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,15 @@
3131

3232
/**
3333
* Generate the various fragments of code needed to register a bean.
34-
* <p>
35-
* A default implementation is provided that suits most needs and custom code
34+
*
35+
* <p>A default implementation is provided that suits most needs and custom code
3636
* fragments are only expected to be used by library authors having built custom
3737
* arrangement on top of the core container.
38-
* <p>
39-
* Users are not expected to implement this interface directly, but rather extends
40-
* from {@link BeanRegistrationCodeFragmentsDecorator} and only override the
41-
* necessary method(s).
38+
*
39+
* <p>Users are not expected to implement this interface directly, but rather
40+
* extends from {@link BeanRegistrationCodeFragmentsDecorator} and only override
41+
* the necessary method(s).
42+
*
4243
* @author Phillip Webb
4344
* @author Stephane Nicoll
4445
* @since 6.0
@@ -48,12 +49,12 @@
4849
public interface BeanRegistrationCodeFragments {
4950

5051
/**
51-
* The variable name to used when creating the bean definition.
52+
* The variable name used when creating the bean definition.
5253
*/
5354
String BEAN_DEFINITION_VARIABLE = "beanDefinition";
5455

5556
/**
56-
* The variable name to used when creating the bean definition.
57+
* The variable name used when creating the bean definition.
5758
*/
5859
String INSTANCE_SUPPLIER_VARIABLE = "instanceSupplier";
5960

@@ -69,8 +70,7 @@ public interface BeanRegistrationCodeFragments {
6970

7071
/**
7172
* Generate the code that defines the new bean definition instance.
72-
* <p>
73-
* This should declare a variable named {@value BEAN_DEFINITION_VARIABLE}
73+
* <p>This should declare a variable named {@value BEAN_DEFINITION_VARIABLE}
7474
* so that further fragments can refer to the variable to further tune
7575
* the bean definition.
7676
* @param generationContext the generation context
@@ -94,14 +94,13 @@ CodeBlock generateSetBeanDefinitionPropertiesCode(
9494

9595
/**
9696
* Generate the code that sets the instance supplier on the bean definition.
97-
* <p>
98-
* The {@code postProcessors} represent methods to be exposed once the
97+
* <p>The {@code postProcessors} represent methods to be exposed once the
9998
* instance has been created to further configure it. Each method should
10099
* accept two parameters, the {@link RegisteredBean} and the bean
101100
* instance, and should return the modified bean instance.
102101
* @param generationContext the generation context
103102
* @param beanRegistrationCode the bean registration code
104-
* @param instanceSupplierCode the instance supplier code supplier code
103+
* @param instanceSupplierCode the instance supplier code
105104
* @param postProcessors any instance post processors that should be applied
106105
* @return the generated code
107106
* @see #generateInstanceSupplierCode

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class BeanRegistrationCodeGenerator implements BeanRegistrationCode {
5858
this.codeFragments = codeFragments;
5959
}
6060

61+
6162
@Override
6263
public ClassName getClassName() {
6364
return this.className;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ public CodeBlock generateReturnCode(
245245
}
246246

247247
private boolean hasInstanceSupplier() {
248-
return this.registeredBean.getMergedBeanDefinition().getInstanceSupplier() != null;
248+
return (this.registeredBean.getMergedBeanDefinition().getInstanceSupplier() != null);
249249
}
250250

251251
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ public InstanceSupplierCodeGenerator(GenerationContext generationContext,
115115
this.allowDirectSupplierShortcut = allowDirectSupplierShortcut;
116116
}
117117

118+
118119
/**
119120
* Generate the instance supplier code.
120121
* @param registeredBean the bean to handle
@@ -165,7 +166,8 @@ private CodeBlock generateCodeForConstructor(RegisteredBean registeredBean, Cons
165166
hints -> hints.registerType(publicType, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS));
166167
}
167168

168-
if (!isVisible(constructor, constructor.getDeclaringClass())) {
169+
if (!isVisible(constructor, constructor.getDeclaringClass()) ||
170+
registeredBean.getMergedBeanDefinition().hasMethodOverrides()) {
169171
return generateCodeForInaccessibleConstructor(descriptor,
170172
hints -> hints.registerConstructor(constructor, ExecutableMode.INVOKE));
171173
}

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.lang.reflect.Method;
2020
import java.util.ArrayList;
21+
import java.util.Collections;
2122
import java.util.List;
2223
import java.util.Objects;
2324

@@ -54,6 +55,20 @@ public ReplaceOverride(String methodName, String methodReplacerBeanName) {
5455
this.methodReplacerBeanName = methodReplacerBeanName;
5556
}
5657

58+
/**
59+
* Construct a new ReplaceOverride.
60+
* @param methodName the name of the method to override
61+
* @param methodReplacerBeanName the bean name of the {@link MethodReplacer}
62+
* @param typeIdentifiers a list of type identifiers for parameter types
63+
* @since 6.2.9
64+
*/
65+
public ReplaceOverride(String methodName, String methodReplacerBeanName, List<String> typeIdentifiers) {
66+
super(methodName);
67+
Assert.notNull(methodReplacerBeanName, "Method replacer bean name must not be null");
68+
this.methodReplacerBeanName = methodReplacerBeanName;
69+
this.typeIdentifiers.addAll(typeIdentifiers);
70+
}
71+
5772

5873
/**
5974
* Return the name of the bean implementing MethodReplacer.
@@ -71,6 +86,15 @@ public void addTypeIdentifier(String identifier) {
7186
this.typeIdentifiers.add(identifier);
7287
}
7388

89+
/**
90+
* Return the list of registered type identifiers (fragments of a class string).
91+
* @since 6.2.9
92+
* @see #addTypeIdentifier
93+
*/
94+
public List<String> getTypeIdentifiers() {
95+
return Collections.unmodifiableList(this.typeIdentifiers);
96+
}
97+
7498

7599
@Override
76100
public boolean matches(Method method) {

spring-context/src/main/java/org/springframework/context/aot/BeanFactoryInitializationAotContributions.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@
3232
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
3333

3434
/**
35-
* A collection of {@link BeanFactoryInitializationAotContribution AOT
36-
* contributions} obtained from {@link BeanFactoryInitializationAotProcessor AOT
37-
* processors}.
35+
* A collection of {@link BeanFactoryInitializationAotContribution AOT contributions}
36+
* obtained from {@link BeanFactoryInitializationAotProcessor AOT processors}.
3837
*
3938
* @author Phillip Webb
4039
* @since 6.0
@@ -48,23 +47,21 @@ class BeanFactoryInitializationAotContributions {
4847
this(beanFactory, AotServices.factoriesAndBeans(beanFactory));
4948
}
5049

51-
BeanFactoryInitializationAotContributions(DefaultListableBeanFactory beanFactory,
52-
AotServices.Loader loader) {
50+
BeanFactoryInitializationAotContributions(DefaultListableBeanFactory beanFactory, AotServices.Loader loader) {
5351
this.contributions = getContributions(beanFactory, getProcessors(loader));
5452
}
5553

5654

57-
private static List<BeanFactoryInitializationAotProcessor> getProcessors(
58-
AotServices.Loader loader) {
55+
private static List<BeanFactoryInitializationAotProcessor> getProcessors(AotServices.Loader loader) {
5956
List<BeanFactoryInitializationAotProcessor> processors = new ArrayList<>(
6057
loader.load(BeanFactoryInitializationAotProcessor.class).asList());
6158
processors.add(new RuntimeHintsBeanFactoryInitializationAotProcessor());
6259
return Collections.unmodifiableList(processors);
6360
}
6461

6562
private List<BeanFactoryInitializationAotContribution> getContributions(
66-
DefaultListableBeanFactory beanFactory,
67-
List<BeanFactoryInitializationAotProcessor> processors) {
63+
DefaultListableBeanFactory beanFactory, List<BeanFactoryInitializationAotProcessor> processors) {
64+
6865
List<BeanFactoryInitializationAotContribution> contributions = new ArrayList<>();
6966
for (BeanFactoryInitializationAotProcessor processor : processors) {
7067
BeanFactoryInitializationAotContribution contribution = processAheadOfTime(processor, beanFactory);
@@ -75,8 +72,8 @@ private List<BeanFactoryInitializationAotContribution> getContributions(
7572
return Collections.unmodifiableList(contributions);
7673
}
7774

78-
private @Nullable BeanFactoryInitializationAotContribution processAheadOfTime(BeanFactoryInitializationAotProcessor processor,
79-
DefaultListableBeanFactory beanFactory) {
75+
private @Nullable BeanFactoryInitializationAotContribution processAheadOfTime(
76+
BeanFactoryInitializationAotProcessor processor, DefaultListableBeanFactory beanFactory) {
8077

8178
try {
8279
return processor.processAheadOfTime(beanFactory);
@@ -92,6 +89,7 @@ private List<BeanFactoryInitializationAotContribution> getContributions(
9289

9390
void applyTo(GenerationContext generationContext,
9491
BeanFactoryInitializationCode beanFactoryInitializationCode) {
92+
9593
for (BeanFactoryInitializationAotContribution contribution : this.contributions) {
9694
contribution.applyTo(generationContext, beanFactoryInitializationCode);
9795
}

0 commit comments

Comments
 (0)