From 684d6ab553c86808cc29ce452d8b95c53102fab4 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 4 Oct 2016 22:39:08 +0200 Subject: [PATCH] @Lookup reference documentation Issue: SPR-14765 --- src/asciidoc/core-beans.adoc | 69 +++++++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 13 deletions(-) diff --git a/src/asciidoc/core-beans.adoc b/src/asciidoc/core-beans.adoc index c80cb2dadb5..80ece4cfb9e 100644 --- a/src/asciidoc/core-beans.adoc +++ b/src/asciidoc/core-beans.adoc @@ -2103,7 +2103,6 @@ overrides the method. in particular not with `@Bean` methods in configuration classes, since the container is not in charge of creating the instance in that case and therefore cannot create a runtime-generated subclass on the fly. -* Finally, objects that have been the target of method injection cannot be serialized. ==== Looking at the `CommandManager` class in the previous code snippet, you see that the @@ -2150,30 +2149,72 @@ the original class. For example: [subs="verbatim,quotes"] ---- - + - + ---- The bean identified as __commandManager__ calls its own method `createCommand()` -whenever it needs a new instance of the __command__ bean. You must be careful to deploy -the `command` bean as a prototype, if that is actually what is needed. If it is deployed -as a <>, the same instance of the `command` +whenever it needs a new instance of the __myCommand__ bean. You must be careful to deploy +the `myCommand` bean as a prototype, if that is actually what is needed. If it is + as a <>, the same instance of the `myCommand` bean is returned each time. +Alternatively, within the annotation-based component model, you may declare a lookup +method through the `@Lookup` annotation: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public abstract class CommandManager { + + public Object process(Object commandState) { + Command command = createCommand(); + command.setState(commandState); + return command.execute(); + } + + @Lookup("myCommand") + protected abstract Command createCommand(); + } +---- + +Or, more idiomatically, you may rely on the target bean getting resolved against the +declared return type of the lookup method: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + public abstract class CommandManager { + + public Object process(Object commandState) { + MyCommand command = createCommand(); + command.setState(commandState); + return command.execute(); + } + + @Lookup + protected abstract MyCommand createCommand(); + } +---- + +Note that you will typically declare such annotated lookup methods with a concrete +stub implementation, in order for them to be compatible with Spring's component +scanning rules where abstract classes get ignored by default. This limitation does not +apply in case of explicitly registered or explicitly imported bean classes. + [TIP] ==== +Another way of accessing differently scoped target beans is an `ObjectFactory`/ +`Provider` injection point. Check out <>. + The interested reader may also find the `ServiceLocatorFactoryBean` (in the -`org.springframework.beans.factory.config` package) to be of use. The approach used in -ServiceLocatorFactoryBean is similar to that of another utility class, -`ObjectFactoryCreatingFactoryBean`, but it allows you to specify your own lookup -interface as opposed to a Spring-specific lookup interface. Consult the javadocs of -these classes for additional information. +`org.springframework.beans.factory.config` package) to be of use. ==== @@ -2616,6 +2657,9 @@ constructor/setter argument or autowired field) as `ObjectFactory` allowing for a `getObject()` call to retrieve the current instance on demand every time it is needed - without holding on to the instance or storing it separately. +As an extended variant, you may declare `ObjectProvider` which delivers +several additional access variants, including `getIfAvailable` and `getIfUnique`. + The JSR-330 variant of this is called `Provider`, used with a `Provider` declaration and a corresponding `get()` call for every retrieval attempt. See <> for more details on JSR-330 overall. @@ -6591,10 +6635,9 @@ type of configuration provides a natural means for implementing this pattern. public Object process(Object commandState) { // grab a new instance of the appropriate Command interface Command command = createCommand(); - // set the state on the (hopefully brand new) Command instance command.setState(commandState); - return command.execute(); + return command.execute(); } // okay... but where is the implementation of this method?