From fab3633c7504686f8ab89a4449e2cf910014388f Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 30 Apr 2024 15:45:46 +0200 Subject: [PATCH 1/3] Add notes on constructor and factory method overloading Closes gh-32091 --- .../ROOT/pages/core/beans/definition.adoc | 28 ++++++++++++++++--- .../server-setup-options.adoc | 3 +- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/core/beans/definition.adoc b/framework-docs/modules/ROOT/pages/core/beans/definition.adoc index 2141abd706..8de9ff4a17 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/definition.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/definition.adoc @@ -234,6 +234,10 @@ For details about the mechanism for supplying arguments to the constructor (if r and setting object instance properties after the object is constructed, see xref:core/beans/dependencies/factory-collaborators.adoc[Injecting Dependencies]. +NOTE: In the case of constructor arguments, the container can select a corresponding +constructor among several overloaded constructors. That said, to avoid ambiguities, +it is recommended to keep your constructor signatures as straightforward as possible. + [[beans-factory-class-static-factory-method]] === Instantiation with a Static Factory Method @@ -294,6 +298,24 @@ For details about the mechanism for supplying (optional) arguments to the factor and setting object instance properties after the object is returned from the factory, see xref:core/beans/dependencies/factory-properties-detailed.adoc[Dependencies and Configuration in Detail]. +NOTE: In the case of factory method arguments, the container can select a corresponding +method among several overloaded methods of the same name. That said, to avoid ambiguities, +it is recommended to keep your factory method signatures as straightforward as possible. + +[TIP] +==== +A typical problematic case with factory method overloading is Mockito with its many +overloads of the `mock` method. Choose the most specific variant of `mock` possible: + +[source,xml,indent=0,subs="verbatim,quotes"] +---- + + + + +---- +==== + [[beans-factory-class-instance-factory-method]] === Instantiation by Using an Instance Factory Method @@ -416,8 +438,8 @@ Kotlin:: ====== This approach shows that the factory bean itself can be managed and configured through -dependency injection (DI). See xref:core/beans/dependencies/factory-properties-detailed.adoc[Dependencies and Configuration in Detail] -. +dependency injection (DI). +See xref:core/beans/dependencies/factory-properties-detailed.adoc[Dependencies and Configuration in Detail]. NOTE: In Spring documentation, "factory bean" refers to a bean that is configured in the Spring container and that creates objects through an @@ -444,5 +466,3 @@ cases into account and returns the type of object that a `BeanFactory.getBean` c going to return for the same bean name. - - diff --git a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc b/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc index 9dd0498d4e..2abf6919d5 100644 --- a/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc +++ b/framework-docs/modules/ROOT/pages/testing/spring-mvc-test-framework/server-setup-options.adoc @@ -111,7 +111,8 @@ a mock service with Mockito: [source,xml,indent=0,subs="verbatim,quotes"] ---- - + + ---- From 72637715528187ef9c87670d371761abb4749f45 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 30 Apr 2024 15:45:56 +0200 Subject: [PATCH 2/3] Add documentation for CompletableFuture-driven rollback Closes gh-32709 --- .../transaction/declarative/annotations.adoc | 16 ++++++----- .../transaction/declarative/rolling-back.adoc | 28 ++++++++++++++++++- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/annotations.adoc b/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/annotations.adoc index c8a83923b5..a866ccb564 100644 --- a/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/annotations.adoc +++ b/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/annotations.adoc @@ -74,10 +74,11 @@ Kotlin:: ---- ====== -Used at the class level as above, the annotation indicates a default for all methods of -the declaring class (as well as its subclasses). Alternatively, each method can be -annotated individually. See xref:data-access/transaction/declarative/annotations.adoc#transaction-declarative-annotations-method-visibility[method visibility] for -further details on which methods Spring considers transactional. Note that a class-level +Used at the class level as above, the annotation indicates a default for all methods +of the declaring class (as well as its subclasses). Alternatively, each method can be +annotated individually. See +xref:data-access/transaction/declarative/annotations.adoc#transaction-declarative-annotations-method-visibility[method visibility] +for further details on which methods Spring considers transactional. Note that a class-level annotation does not apply to ancestor classes up the class hierarchy; in such a scenario, inherited methods need to be locally redeclared in order to participate in a subclass-level annotation. @@ -436,9 +437,10 @@ properties of the `@Transactional` annotation: | Optional array of exception name patterns that must not cause rollback. |=== -TIP: See xref:data-access/transaction/declarative/rolling-back.adoc#transaction-declarative-rollback-rules[Rollback rules] for further details -on rollback rule semantics, patterns, and warnings regarding possible unintentional -matches for pattern-based rollback rules. +TIP: See +xref:data-access/transaction/declarative/rolling-back.adoc#transaction-declarative-rollback-rules[Rollback rules] +for further details on rollback rule semantics, patterns, and warnings +regarding possible unintentional matches for pattern-based rollback rules. Currently, you cannot have explicit control over the name of a transaction, where 'name' means the transaction name that appears in a transaction monitor and in logging output. diff --git a/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/rolling-back.adoc b/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/rolling-back.adoc index 1de4c5af25..166fb73243 100644 --- a/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/rolling-back.adoc +++ b/framework-docs/modules/ROOT/pages/data-access/transaction/declarative/rolling-back.adoc @@ -24,8 +24,8 @@ Vavr's `Try` method to trigger transaction rollbacks when it returns a 'Failure' This allows you to handle functional-style errors using Try and have the transaction automatically rolled back in case of a failure. For more information on Vavr's Try, refer to the https://docs.vavr.io/#_try[official Vavr documentation]. - Here's an example of how to use Vavr's Try with a transactional method: + [tabs] ====== Java:: @@ -42,6 +42,32 @@ Java:: ---- ====== +As of Spring Framework 6.1, there is also special treatment of `CompletableFuture` +(and general `Future`) return values, triggering a rollback for such a handle if it +was exceptionally completed at the time of being returned from the original method. +This is intended for `@Async` methods where the actual method implementation may +need to comply with a `CompletableFuture` signature (auto-adapted to an actual +asynchronous handle for a call to the proxy by `@Async` processing at runtime), +preferring exposure in the returned handle rather than rethrowing an exception: + +[tabs] +====== +Java:: ++ +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +---- + @Transactional @Async + public CompletableFuture myTransactionalMethod() { + try { + return CompletableFuture.completedFuture(delegate.myDataAccessOperation()); + } + catch (DataAccessException ex) { + return CompletableFuture.failedFuture(ex); + } + } +---- +====== + Checked exceptions that are thrown from a transactional method do not result in a rollback in the default configuration. You can configure exactly which `Exception` types mark a transaction for rollback, including checked exceptions by specifying _rollback rules_. From cbda46984c754545e35e8724be8e4d39997ce7f2 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 30 Apr 2024 15:46:28 +0200 Subject: [PATCH 3/3] Polishing --- .../springframework/aop/framework/AdvisedSupport.java | 3 +-- .../beans/factory/support/RegisteredBean.java | 10 +++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java b/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java index 5cd193c89f..2aebe1688d 100644 --- a/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java +++ b/spring-aop/src/main/java/org/springframework/aop/framework/AdvisedSupport.java @@ -369,8 +369,7 @@ public class AdvisedSupport extends ProxyConfig implements Advised { private void validateIntroductionAdvisor(IntroductionAdvisor advisor) { advisor.validateInterfaces(); // If the advisor passed validation, we can make the change. - Class[] ifcs = advisor.getInterfaces(); - for (Class ifc : ifcs) { + for (Class ifc : advisor.getInterfaces()) { addInterface(ifc); } } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java index 791a450f8c..da3b8e6ec3 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/RegisteredBean.java @@ -43,6 +43,8 @@ import org.springframework.util.StringUtils; * In the case of inner-beans, the bean name may have been generated. * * @author Phillip Webb + * @author Stephane Nicoll + * @author Juergen Hoeller * @since 6.0 */ public final class RegisteredBean { @@ -262,9 +264,11 @@ public final class RegisteredBean { /** * Descriptor for how a bean should be instantiated. While the {@code targetClass} - * is usually the declaring class of the {@code executable}, there are cases - * where retaining the actual concrete type is necessary. - * @param executable the {@link Executable} to invoke + * is usually the declaring class of the {@code executable} (in case of a constructor + * or a locally declared factory method), there are cases where retaining the actual + * concrete class is necessary (e.g. for an inherited factory method). + * @param executable the {@link Executable} ({@link java.lang.reflect.Constructor} + * or {@link java.lang.reflect.Method}) to invoke * @param targetClass the target {@link Class} of the executable * @since 6.1.7 */