From 2952cb95f500cc9d4d8c28e197e34159e731b29f Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 21 Aug 2023 12:32:33 +0200 Subject: [PATCH 1/3] Document custom SimpleApplicationEventMulticaster setup Closes gh-29996 --- .../core/beans/context-introduction.adoc | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/core/beans/context-introduction.adoc b/framework-docs/modules/ROOT/pages/core/beans/context-introduction.adoc index 44e766609b..16e9531eea 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/context-introduction.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/context-introduction.adoc @@ -484,13 +484,14 @@ custom event (`BlockedListEvent` in the preceding example). This means that the You can register as many event listeners as you wish, but note that, by default, event listeners receive events synchronously. This means that the `publishEvent()` method blocks until all listeners have finished processing the event. One advantage of this -synchronous and single-threaded approach is that, when a listener receives an event, it -operates inside the transaction context of the publisher if a transaction context is -available. If another strategy for event publication becomes necessary, see the javadoc -for Spring's +synchronous and single-threaded approach is that, when a listener receives an event, +it operates inside the transaction context of the publisher if a transaction context +is available. If another strategy for event publication becomes necessary, e.g. +asynchronous event processing by default, see the javadoc for Spring's {api-spring-framework}/context/event/ApplicationEventMulticaster.html[`ApplicationEventMulticaster`] interface and {api-spring-framework}/context/event/SimpleApplicationEventMulticaster.html[`SimpleApplicationEventMulticaster`] -implementation for configuration options. +implementation for configuration options which can be applied to a custom +"applicationEventMulticaster" bean definition. The following example shows the bean definitions used to register and configure each of the classes above: @@ -510,6 +511,12 @@ the classes above: + + + + + + ---- Putting it all together, when the `sendEmail()` method of the `emailService` bean is @@ -849,6 +856,23 @@ Kotlin:: TIP: This works not only for `ApplicationEvent` but any arbitrary object that you send as an event. +Finally, as with classic `ApplicationListener` implementations, the actual multicasting +happens via a context-wide `ApplicationEventMulticaster` at runtime. By default, this is a +`SimpleApplicationEventMulticaster` with synchronous event publication in the caller thread. +This can be replaced/customized through an "applicationEventMulticaster" bean definition, +e.g. for processing all events asynchronously and/or for handling listener exceptions: + +[source,java,indent=0,subs="verbatim,quotes"] +---- + @Bean + ApplicationEventMulticaster applicationEventMulticaster() { + SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster(); + multicaster.setTaskExecutor(...); + multicaster.setErrorHandler(...); + return multicaster; + } +---- + [[context-functionality-resources]] From b0fc2fe473414324732393fad44172390577e19d Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 21 Aug 2023 12:32:45 +0200 Subject: [PATCH 2/3] Document destroy method inference more prominently Closes gh-29546 --- .../ROOT/pages/core/beans/factory-nature.adoc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/core/beans/factory-nature.adoc b/framework-docs/modules/ROOT/pages/core/beans/factory-nature.adoc index e3a1204295..c23676f938 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/factory-nature.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/factory-nature.adoc @@ -247,14 +247,17 @@ Kotlin:: However, the first of the two preceding definitions does not couple the code to Spring. -TIP: You can assign the `destroy-method` attribute of a `` element a special -`(inferred)` value, which instructs Spring to automatically detect a public `close` -or `shutdown` method on the specific bean class. (Any class that implements -`java.lang.AutoCloseable` or `java.io.Closeable` would therefore match.) You can also -set this special `(inferred)` value on the `default-destroy-method` attribute of a -`` element to apply this behavior to an entire set of beans (see +Note that Spring also supports inference of destroy methods, detecting a public `close` or +`shutdown` method. This is the default behavior for `@Bean` methods in Java configuration +classes and automatically matches `java.lang.AutoCloseable` or `java.io.Closeable` +implementations, not coupling the destruction logic to Spring either. + +TIP: For destroy method inference with XML, you may assign the `destroy-method` attribute +of a `` element a special `(inferred)` value, which instructs Spring to automatically +detect a public `close` or `shutdown` method on the bean class for a specific bean definition. +You can also set this special `(inferred)` value on the `default-destroy-method` attribute +of a `` element to apply this behavior to an entire set of bean definitions (see xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-default-init-destroy-methods[Default Initialization and Destroy Methods]). -Note that this is the default behavior for `@Bean` methods in Java configuration classes. [NOTE] ==== From 8a6c0cd221d1b9b78acf26a60121d51f0446d6b3 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 21 Aug 2023 12:37:58 +0200 Subject: [PATCH 3/3] Polishing --- .../modules/ROOT/pages/core/beans/basics.adoc | 23 +++++++++++-------- .../pages/core/beans/factory-extension.adoc | 23 +++++++++---------- .../ROOT/pages/core/beans/factory-scopes.adoc | 13 ++++++----- .../core/beans/java/bean-annotation.adoc | 18 ++++++++------- 4 files changed, 41 insertions(+), 36 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/core/beans/basics.adoc b/framework-docs/modules/ROOT/pages/core/beans/basics.adoc index b3deb285d7..57e51a6f1e 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/basics.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/basics.adoc @@ -22,10 +22,11 @@ additional metadata formats. In most application scenarios, explicit user code is not required to instantiate one or more instances of a Spring IoC container. For example, in a web application scenario, a simple eight (or so) lines of boilerplate web descriptor XML in the `web.xml` file -of the application typically suffices (see xref:core/beans/context-introduction.adoc#context-create[Convenient ApplicationContext Instantiation for Web Applications]). If you use the -https://spring.io/tools[Spring Tools for Eclipse] (an Eclipse-powered development -environment), you can easily create this boilerplate configuration with a few mouse clicks or -keystrokes. +of the application typically suffices (see +xref:core/beans/context-introduction.adoc#context-create[Convenient ApplicationContext Instantiation for Web Applications]). +If you use the https://spring.io/tools[Spring Tools for Eclipse] (an Eclipse-powered +development environment), you can easily create this boilerplate configuration with a +few mouse clicks or keystrokes. The following diagram shows a high-level view of how Spring works. Your application classes are combined with configuration metadata so that, after the `ApplicationContext` is @@ -139,9 +140,11 @@ Kotlin:: [NOTE] ==== After you learn about Spring's IoC container, you may want to know more about Spring's -`Resource` abstraction (as described in xref:web/webflux-webclient/client-builder.adoc#webflux-client-builder-reactor-resources[Resources]), which provides a convenient -mechanism for reading an InputStream from locations defined in a URI syntax. In particular, -`Resource` paths are used to construct applications contexts, as described in xref:core/resources.adoc#resources-app-ctx[Application Contexts and Resource Paths]. +`Resource` abstraction (as described in +xref:web/webflux-webclient/client-builder.adoc#webflux-client-builder-reactor-resources[Resources]) +which provides a convenient mechanism for reading an InputStream from locations defined +in a URI syntax. In particular, `Resource` paths are used to construct applications contexts, +as described in xref:core/resources.adoc#resources-app-ctx[Application Contexts and Resource Paths]. ==== The following example shows the service layer objects `(services.xml)` configuration file: @@ -208,9 +211,9 @@ XML configuration file represents a logical layer or module in your architecture You can use the application context constructor to load bean definitions from all these XML fragments. This constructor takes multiple `Resource` locations, as was shown in the -xref:core/beans/basics.adoc#beans-factory-instantiation[previous section]. Alternatively, use one or more -occurrences of the `` element to load bean definitions from another file or -files. The following example shows how to do so: +xref:core/beans/basics.adoc#beans-factory-instantiation[previous section]. Alternatively, +use one or more occurrences of the `` element to load bean definitions from +another file or files. The following example shows how to do so: [source,xml,indent=0,subs="verbatim,quotes"] ---- diff --git a/framework-docs/modules/ROOT/pages/core/beans/factory-extension.adoc b/framework-docs/modules/ROOT/pages/core/beans/factory-extension.adoc index 6882cdb7ad..3e7a095d9c 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/factory-extension.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/factory-extension.adoc @@ -23,9 +23,8 @@ You can set this property only if the `BeanPostProcessor` implements the `Ordere interface. If you write your own `BeanPostProcessor`, you should consider implementing the `Ordered` interface, too. For further details, see the javadoc of the {api-spring-framework}/beans/factory/config/BeanPostProcessor.html[`BeanPostProcessor`] -and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces. See also the note -on xref:core/beans/factory-extension.adoc#beans-factory-programmatically-registering-beanpostprocessors[programmatic registration of `BeanPostProcessor` instances] -. +and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces. See also the note on +xref:core/beans/factory-extension.adoc#beans-factory-programmatically-registering-beanpostprocessors[programmatic registration of `BeanPostProcessor` instances]. [NOTE] ==== @@ -280,11 +279,12 @@ and {api-spring-framework}/core/Ordered.html[`Ordered`] interfaces for more deta ==== If you want to change the actual bean instances (that is, the objects that are created from the configuration metadata), then you instead need to use a `BeanPostProcessor` -(described earlier in xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp[Customizing Beans by Using a `BeanPostProcessor`]). While it is technically possible -to work with bean instances within a `BeanFactoryPostProcessor` (for example, by using -`BeanFactory.getBean()`), doing so causes premature bean instantiation, violating the -standard container lifecycle. This may cause negative side effects, such as bypassing -bean post processing. +(described earlier in +xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp[Customizing Beans by Using a `BeanPostProcessor`]). +While it is technically possible to work with bean instances within a `BeanFactoryPostProcessor` +(for example, by using `BeanFactory.getBean()`), doing so causes premature bean instantiation, +violating the standard container lifecycle. This may cause negative side effects, such as +bypassing bean post processing. Also, `BeanFactoryPostProcessor` instances are scoped per-container. This is only relevant if you use container hierarchies. If you define a `BeanFactoryPostProcessor` in one @@ -331,8 +331,7 @@ with placeholder values is defined: - + @@ -433,8 +432,8 @@ This example file can be used with a container definition that contains a bean c Compound property names are also supported, as long as every component of the path except the final property being overridden is already non-null (presumably initialized -by the constructors). In the following example, the `sammy` property of the `bob` property of the `fred` property of the `tom` bean -is set to the scalar value `123`: +by the constructors). In the following example, the `sammy` property of the `bob` +property of the `fred` property of the `tom` bean is set to the scalar value `123`: [literal,subs="verbatim,quotes"] ---- diff --git a/framework-docs/modules/ROOT/pages/core/beans/factory-scopes.adoc b/framework-docs/modules/ROOT/pages/core/beans/factory-scopes.adoc index 6a835bebb2..261f8d1e61 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/factory-scopes.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/factory-scopes.adoc @@ -125,8 +125,8 @@ objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype beans hold. To get the Spring container to release resources held by prototype-scoped beans, try using a -custom xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp[bean post-processor], which holds a reference to -beans that need to be cleaned up. +custom xref:core/beans/factory-extension.adoc#beans-factory-extension-bpp[bean post-processor] +which holds a reference to beans that need to be cleaned up. In some respects, the Spring container's role in regard to a prototype-scoped bean is a replacement for the Java `new` operator. All lifecycle management past that point must @@ -449,12 +449,13 @@ understand the "`why`" as well as the "`how`" behind it: ---- <1> The line that defines the proxy. +To create such a proxy, you insert a child `` element into a +scoped bean definition (see +xref:core/beans/factory-scopes.adoc#beans-factory-scopes-other-injection-proxies[Choosing the Type of Proxy to Create] +and xref:core/appendix/xsd-schemas.adoc[XML Schema-based configuration]). -To create such a proxy, you insert a child `` element into a scoped -bean definition (see xref:core/beans/factory-scopes.adoc#beans-factory-scopes-other-injection-proxies[Choosing the Type of Proxy to Create] and -xref:core/appendix/xsd-schemas.adoc[XML Schema-based configuration]). Why do definitions of beans scoped at the `request`, `session` and custom-scope -levels require the `` element? +levels require the `` element in common scenarios? Consider the following singleton bean definition and contrast it with what you need to define for the aforementioned scopes (note that the following `userPreferences` bean definition as it stands is incomplete): diff --git a/framework-docs/modules/ROOT/pages/core/beans/java/bean-annotation.adoc b/framework-docs/modules/ROOT/pages/core/beans/java/bean-annotation.adoc index 52089db3c5..dd35cefa9d 100644 --- a/framework-docs/modules/ROOT/pages/core/beans/java/bean-annotation.adoc +++ b/framework-docs/modules/ROOT/pages/core/beans/java/bean-annotation.adoc @@ -180,9 +180,10 @@ Kotlin:: ---- ====== - The resolution mechanism is pretty much identical to constructor-based dependency -injection. See xref:core/beans/dependencies/factory-collaborators.adoc#beans-constructor-injection[the relevant section] for more details. +injection. See +xref:core/beans/dependencies/factory-collaborators.adoc#beans-constructor-injection[the relevant section] +for more details. [[beans-java-lifecycle-callbacks]] @@ -317,8 +318,9 @@ type, making it harder to use for cross-reference calls in other `@Bean` methods intend to refer to the provided resource here). ===== -In the case of `BeanOne` from the example above the preceding note, it would be equally valid to call the `init()` -method directly during construction, as the following example shows: +In the case of `BeanOne` from the example above the preceding note, it would be +equally valid to call the `init()` method directly during construction, as the +following example shows: [tabs] ====== @@ -506,10 +508,10 @@ Kotlin:: [[beans-java-bean-aliasing]] == Bean Aliasing -As discussed in xref:core/beans/definition.adoc#beans-beanname[Naming Beans], it is sometimes desirable to give a single bean -multiple names, otherwise known as bean aliasing. The `name` attribute of the `@Bean` -annotation accepts a String array for this purpose. The following example shows how to set -a number of aliases for a bean: +As discussed in xref:core/beans/definition.adoc#beans-beanname[Naming Beans], it is +sometimes desirable to give a single bean multiple names, otherwise known as bean aliasing. +The `name` attribute of the `@Bean` annotation accepts a String array for this purpose. +The following example shows how to set a number of aliases for a bean: [tabs] ======