From f58e1db2e69b2bc0bcb4da7d83c01c1c9b56695d Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 7 Jul 2015 16:49:26 +0200 Subject: [PATCH] Explicit notes for @Bean on static methods, private methods, and Java 8 default methods Also includes an explicit note on stop vs destroy callbacks for Lifecycle beans. Issue: SPR-13118 Issue: SPR-12882 Issue: SPR-12345 Issue: SPR-11671 --- .../springframework/context/Lifecycle.java | 26 ++++++---- src/asciidoc/core-beans.adoc | 50 ++++++++++++++++--- 2 files changed, 57 insertions(+), 19 deletions(-) diff --git a/spring-context/src/main/java/org/springframework/context/Lifecycle.java b/spring-context/src/main/java/org/springframework/context/Lifecycle.java index 4d52031dcd..16060116bb 100644 --- a/spring-context/src/main/java/org/springframework/context/Lifecycle.java +++ b/spring-context/src/main/java/org/springframework/context/Lifecycle.java @@ -50,29 +50,33 @@ public interface Lifecycle { /** * Start this component. - * Should not throw an exception if the component is already running. - *

In the case of a container, this will propagate the start signal - * to all components that apply. + *

Should not throw an exception if the component is already running. + *

In the case of a container, this will propagate the start signal to all + * components that apply. * @see SmartLifecycle#isAutoStartup() */ void start(); /** - * Stop this component, typically in a synchronous fashion, such that - * the component is fully stopped upon return of this method. Consider - * implementing {@link SmartLifecycle} and its {@code stop(Runnable)} - * variant in cases where asynchronous stop behavior is necessary. + * Stop this component, typically in a synchronous fashion, such that the component is + * fully stopped upon return of this method. Consider implementing {@link SmartLifecycle} + * and its {@code stop(Runnable)} variant when asynchronous stop behavior is necessary. + *

Note that this stop notification is not guaranteed to come before destruction: On + * regular shutdown, {@code Lifecycle} beans will first receive a stop notification before + * the general destruction callbacks are being propagated; however, on hot refresh during a + * context's lifetime or on aborted refresh attempts, only destroy methods will be called. *

Should not throw an exception if the component isn't started yet. - *

In the case of a container, this will propagate the stop signal - * to all components that apply. + *

In the case of a container, this will propagate the stop signal to all components + * that apply. * @see SmartLifecycle#stop(Runnable) + * @see org.springframework.beans.factory.DisposableBean#destroy() */ void stop(); /** * Check whether this component is currently running. - *

In the case of a container, this will return {@code true} - * only if all components that apply are currently running. + *

In the case of a container, this will return {@code true} only if all + * components that apply are currently running. * @return whether the component is currently running */ boolean isRunning(); diff --git a/src/asciidoc/core-beans.adoc b/src/asciidoc/core-beans.adoc index e5b31e42f2..8254d9b330 100644 --- a/src/asciidoc/core-beans.adoc +++ b/src/asciidoc/core-beans.adoc @@ -2849,7 +2849,7 @@ unnecessarily couples the code to Spring. Alternatively, use the <> annotation or specify a POJO initialization method. In the case of XML-based configuration metadata, you use the `init-method` attribute to specify the name of the method that has a void -no-argument signature. With Java config you use the `initMethod` attribute of `@Bean`, +no-argument signature. With Java config, you use the `initMethod` attribute of `@Bean`, see <>. For example, the following: [source,xml,indent=0] @@ -2909,8 +2909,8 @@ It is recommended that you do not use the `DisposableBean` callback interface be unnecessarily couples the code to Spring. Alternatively, use the <> annotation or specify a generic method that is supported by bean definitions. With XML-based -configuration metadata, you use the `destroy-method` attribute on the ``. With -Java config you use the `destroyMethod` attribute of `@Bean`, see +configuration metadata, you use the `destroy-method` attribute on the ``. +With Java config, you use the `destroyMethod` attribute of `@Bean`, see <>. For example, the following definition: [source,xml,indent=0] @@ -3122,6 +3122,10 @@ Note that the regular `org.springframework.context.Lifecycle` interface is just contract for explicit start/stop notifications and does NOT imply auto-startup at context refresh time. Consider implementing `org.springframework.context.SmartLifecycle` instead for fine-grained control over auto-startup of a specific bean (including startup phases). +Also, please note that stop notifications are not guaranteed to come before destruction: +On regular shutdown, all `Lifecycle` beans will first receive a stop notification before +the general destruction callbacks are being propagated; however, on hot refresh during a +context's lifetime or on aborted refresh attempts, only destroy methods will be called. ==== The order of startup and shutdown invocations can be important. If a "depends-on" @@ -5128,8 +5132,8 @@ will in effect disable automatic detection of classes annotated with `@Component [[beans-factorybeans-annotations]] === Defining bean metadata within components Spring components can also contribute bean definition metadata to the container. You do -this with the same `@Bean` annotation used to define bean metadata within -`@Configuration` annotated classes. Here is a simple example: +this with the same `@Bean` annotation used to define bean metadata within `@Configuration` +annotated classes. Here is a simple example: [source,java,indent=0] [subs="verbatim,quotes"] @@ -5219,9 +5223,39 @@ counterparts inside a Spring `@Configuration` class. The difference is that `@Co classes are not enhanced with CGLIB to intercept the invocation of methods and fields. CGLIB proxying is the means by which invoking methods or fields within `@Bean` methods in `@Configuration` classes creates bean metadata references to collaborating objects; -such methods are __not__ invoked with normal Java semantics. In contrast, invoking a -method or field in an `@Bean` method within a `@Component` class __has__ standard Java -semantics. +such methods are __not__ invoked with normal Java semantics but rather go through the +container in order to provide the usual lifecycle management and proxying of Spring +beans even when referring to other beans via programmatic calls to `@Bean` methods. +In contrast, invoking a method or field in an `@Bean` method within a plain `@Component` +class __has__ standard Java semantics, with no special CGLIB processing or other +constraints applying. + +[NOTE] +==== +You may declare `@Bean` methods as `static`, allowing for them to be called without +creating their containing configuration class as an instance. This makes particular +sense when defining post-processor beans, e.g. of type `BeanFactoryPostProcessor` or +`BeanPostProcessor`, since such beans will get initialized early in the container +lifecycle and should avoid triggering other parts of the configuration at that point. + +Note that calls to static `@Bean` methods will never get intercepted by the container, +not even within `@Configuration` classes (see above). This is due to technical +limitations: CGLIB subclassing can only override non-static methods. As a consequence, +a direct call to another `@Bean` method will have standard Java semantics, resulting +in an independent instance being returned straight from the factory method itself. + +The Java language visibility of `@Bean` methods does not have an immediate impact on +the resulting bean definition in Spring's container. You may freely declare your +factory methods as you see fit in non-`@Configuration` classes and also for static +methods anywhere. However, regular `@Bean` methods in `@Configuration` classes need +to be overridable, i.e. they must not be declared as `private` or `final`. + +Finally, `@Bean` methods will also be discovered on base classes of a given component +or configuration class, as well as on Java 8 default methods declared in interfaces +implemented by the component or configuration class. This allows for a lot of +flexibility in composing complex configuration arrangements, with even multiple +inheritance being possible through Java 8 default methods as of Spring 4.2. +====