Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve documentation on inferred destruction callbacks #30745

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion framework-docs/antora.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ nav:
ext:
collector:
run:
command: gradlew -q -PbuildSrc.skipTests=true "-Dorg.gradle.jvmargs=-Xmx3g -XX:+HeapDumpOnOutOfMemoryError" :framework-docs:generateAntoraResources
command: gradlew -q -PbuildSrc.skipTests=true "-Dorg.gradle.jvmargs=-Xmx3g :framework-docs:generateAntoraResources
local: true
scan:
dir: ./build/generated-antora-resources
Expand Down
74 changes: 64 additions & 10 deletions framework-docs/modules/ROOT/pages/core/beans/factory-nature.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,69 @@ However, the first of the two preceding examples does not couple the code to Spr
[[beans-factory-lifecycle-disposablebean]]
=== Destruction Callbacks

Destruction callbacks can be inferred using a `close` or `shutdown` method, or explicit using
`DisposableBean` interface, xref:core/beans/annotation-config/postconstruct-and-predestroy-annotations.adoc[`@PreDestroy`]
annotation or `destroy-method` attribute.

[[beans-factory-lifecycle-destruction-callback-inferred]]
==== Inferred destruction methods

By default, beans defined with Java configuration that have a public `close` or `shutdown`
method are automatically enlisted with a destruction callback. If you have a public
`close` or `shutdown` method and you do not wish for it to be called when the container
shuts down, you can add `@Bean(destroyMethod = "")` to your bean definition to disable the
default `(inferred)` mode.

[NOTE]
=====
You may want to disable the default `(inferred)` mode for a resource that you acquire with JNDI, as its
lifecycle is managed outside the application. In particular, make sure to always do it
for a `DataSource`, as it is known to be problematic on Jakarta EE application servers.

The following example shows how to prevent an automatic destruction callback for a
`DataSource`:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Bean(destroyMethod = "")
public DataSource dataSource() throws NamingException {
return (DataSource) jndiTemplate.lookup("MyDS");
}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@Bean(destroyMethod = "")
fun dataSource(): DataSource {
return jndiTemplate.lookup("MyDS") as DataSource
}
----
======

Also, with `@Bean` methods, you typically use programmatic JNDI lookups, either by
using Spring's `JndiTemplate` or `JndiLocatorDelegate` helpers or straight JNDI
`InitialContext` usage but not the `JndiObjectFactoryBean` variant (which would force
you to declare the return type as the `FactoryBean` type instead of the actual target
type, making it harder to use for cross-reference calls in other `@Bean` methods that
intend to refer to the provided resource here).
=====

In XML Spring configuration, you can assign the `destroy-method` attribute of a `<bean>` element the 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
`<beans>` element to apply this behavior to an entire set of beans (see
xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-default-init-destroy-methods[Default Initialization and Destroy Methods]).

[[beans-factory-lifecycle-destruction-callback-explicit]]
==== Explicit destruction methods
Implementing the `org.springframework.beans.factory.DisposableBean` interface lets a
bean get a callback when the container that contains it is destroyed. The
`DisposableBean` interface specifies a single method:
Expand Down Expand Up @@ -222,15 +285,6 @@ 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 `<bean>` 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
`<beans>` element to apply this behavior to an entire set of beans (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 with Java configuration.

[[beans-factory-lifecycle-default-init-destroy-methods]]
=== Default Initialization and Destroy Methods

Expand Down Expand Up @@ -339,7 +393,7 @@ interacts directly with the raw target bean.
As of Spring 2.5, you have three options for controlling bean lifecycle behavior:

* The xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-initializingbean[`InitializingBean`] and
xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-disposablebean[`DisposableBean`] callback interfaces
xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-destruction-callback-explicit[`DisposableBean`] callback interfaces
* Custom `init()` and `destroy()` methods
* The xref:core/beans/annotation-config/postconstruct-and-predestroy-annotations.adoc[`@PostConstruct` and `@PreDestroy` annotations]
. You can combine these mechanisms to control a given bean.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
The annotation supports some of the attributes offered by `<bean/>`, such as:

* xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-initializingbean[init-method]
* xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-disposablebean[destroy-method]
* xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-destruction-callback-explicit[destroy-method]
* xref:core/beans/dependencies/factory-autowire.adoc[autowiring]
* `name`.

Expand Down Expand Up @@ -193,6 +193,11 @@ and can use the `@PostConstruct` and `@PreDestroy` annotations from JSR-250. See
xref:core/beans/annotation-config/postconstruct-and-predestroy-annotations.adoc[JSR-250 annotations] for further
details.

Any classes defined with the `@Bean` annotation also support inferred destruction methods and detect
any public `close` or `shutdown` method as a destruction callback. See
xref:core/beans/factory-nature.adoc#beans-factory-lifecycle-destruction-callback-inferred[Inferred destruction methods]
for further details.

The regular Spring xref:core/beans/factory-nature.adoc[lifecycle] callbacks are fully supported as
well. If a bean implements `InitializingBean`, `DisposableBean`, or `Lifecycle`, their
respective methods are called by the container.
Expand Down Expand Up @@ -271,52 +276,6 @@ class AppConfig {
----
======

[NOTE]
=====
By default, beans defined with Java configuration that have a public `close` or `shutdown`
method are automatically enlisted with a destruction callback. If you have a public
`close` or `shutdown` method and you do not wish for it to be called when the container
shuts down, you can add `@Bean(destroyMethod = "")` to your bean definition to disable the
default `(inferred)` mode.

You may want to do that by default for a resource that you acquire with JNDI, as its
lifecycle is managed outside the application. In particular, make sure to always do it
for a `DataSource`, as it is known to be problematic on Jakarta EE application servers.

The following example shows how to prevent an automatic destruction callback for a
`DataSource`:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
@Bean(destroyMethod = "")
public DataSource dataSource() throws NamingException {
return (DataSource) jndiTemplate.lookup("MyDS");
}
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
----
@Bean(destroyMethod = "")
fun dataSource(): DataSource {
return jndiTemplate.lookup("MyDS") as DataSource
}
----
======

Also, with `@Bean` methods, you typically use programmatic JNDI lookups, either by
using Spring's `JndiTemplate` or `JndiLocatorDelegate` helpers or straight JNDI
`InitialContext` usage but not the `JndiObjectFactoryBean` variant (which would force
you to declare the return type as the `FactoryBean` type instead of the actual target
type, making it harder to use for cross-reference calls in other `@Bean` methods that
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:

Expand Down