提交 f58e1db2 编写于 作者: J Juergen Hoeller

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
上级 ca3ba7de
......@@ -50,29 +50,33 @@ public interface Lifecycle {
/**
* Start this component.
* Should not throw an exception if the component is already running.
* <p>In the case of a container, this will propagate the start signal
* to all components that apply.
* <p>Should not throw an exception if the component is already running.
* <p>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.
* <p>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.
* <p>Should not throw an exception if the component isn't started yet.
* <p>In the case of a container, this will propagate the stop signal
* to all components that apply.
* <p>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.
* <p>In the case of a container, this will return {@code true}
* only if <i>all</i> components that apply are currently running.
* <p>In the case of a container, this will return {@code true} only if <i>all</i>
* components that apply are currently running.
* @return whether the component is currently running
*/
boolean isRunning();
......
......@@ -2849,7 +2849,7 @@ unnecessarily couples the code to Spring. Alternatively, use
the <<beans-postconstruct-and-predestroy-annotations, `@PostConstruct`>> 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 <<beans-java-lifecycle-callbacks>>. 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 <<beans-postconstruct-and-predestroy-annotations, `@PreDestroy`>> 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 `<bean/>`. With
Java config you use the `destroyMethod` attribute of `@Bean`, see
configuration metadata, you use the `destroy-method` attribute on the `<bean/>`.
With Java config, you use the `destroyMethod` attribute of `@Bean`, see
<<beans-java-lifecycle-callbacks>>. 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.
====
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册