From a13a1eb1f17579954b784618f52664a72df494b6 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 28 Oct 2015 18:27:18 +0100 Subject: [PATCH] Reference documentation for ObjectFactory and JSR-330's Provider Issue: SPR-13117 --- src/asciidoc/core-beans.adoc | 107 ++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 33 deletions(-) diff --git a/src/asciidoc/core-beans.adoc b/src/asciidoc/core-beans.adoc index ec97264cf6..7aceeef33c 100644 --- a/src/asciidoc/core-beans.adoc +++ b/src/asciidoc/core-beans.adoc @@ -2561,18 +2561,33 @@ and it is actually exposed and therefore visible as a `ServletContext` attribute [[beans-factory-scopes-other-injection]] ==== Scoped beans as dependencies -The Spring IoC container manages not only the instantiation of your objects (beans), but -also the wiring up of collaborators (or dependencies). If you want to inject (for -example) an HTTP request scoped bean into another bean, you must inject an AOP proxy in -place of the scoped bean. That is, you need to inject a proxy object that exposes the -same public interface as the scoped object but that can also retrieve the real, target -object from the relevant scope (for example, an HTTP request) and delegate method calls -onto the real object. +The Spring IoC container manages not only the instantiation of your objects (beans), +but also the wiring up of collaborators (or dependencies). If you want to inject (for +example) an HTTP request scoped bean into another bean of a longer-lived scope, you may +choose to inject an AOP proxy in place of the scoped bean. That is, you need to inject +a proxy object that exposes the same public interface as the scoped object but that can +also retrieve the real target object from the relevant scope (such as an HTTP request) +and delegate method calls onto the real object. [NOTE] ==== -You __do not__ need to use the `` in conjunction with beans that are -scoped as `singletons` or `prototypes`. +You may also use `` between beans that are scoped as `singleton`, +with the reference then going through an intermediate proxy that is serializable +and therefore able to re-obtain the target singleton bean on deserialization. + +When declaring `` against a bean of scope `prototype`, every method +call on the shared proxy will lead to the creation of a new target instance which the +call is then being forwarded to. + +Also, scoped proxies are not the only way to access beans from shorter scopes in a +lifecycle-safe fashion. You may also simply declare your injection point (i.e. the +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. + +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. ==== The configuration in the following example is only one line, but it is important to @@ -2654,6 +2669,7 @@ Thus you need the following, correct and complete, configuration when injecting + @@ -2687,6 +2703,7 @@ interfaces. + @@ -4165,8 +4182,8 @@ As expected, you can apply the `@Autowired` annotation to "traditional" setter m [NOTE] ==== -JSR 330's @Inject annotation can be used in place of Spring's `@Autowired` annotation in -the examples below. See <> for more details +JSR 330's `@Inject` annotation can be used in place of Spring's `@Autowired` annotation +in the examples below. See <> for more details. ==== You can also apply the annotation to methods with arbitrary names and/or multiple @@ -5673,15 +5690,37 @@ Instead of `@Autowired`, `@javax.inject.Inject` may be used as follows: this.movieFinder = movieFinder; } - // ... - + public void listMovies() { + this.movieFinder.findMovies(...); + ... + } } ---- -As with `@Autowired`, it is possible to use `@Inject` at the class-level, field-level, -method-level and constructor-argument level. If you would like to use a qualified name -for the dependency that should be injected, you should use the `@Named` annotation as -follows: +As with `@Autowired`, it is possible to use `@Inject` at the field level, method level +and constructor-argument level. Furthermore, you may declare your injection point as a +`Provider`, allowing for on-demand access to beans of shorter scopes or lazy access to +other beans through a `Provider.get()` call. As a variant of the example above: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + import javax.inject.Inject; + import javax.inject.Provider; + + public class SimpleMovieLister { + + private Provider movieFinder; + + public void listMovies() { + this.movieFinder.get().findMovies(...); + ... + } + } +---- + +If you would like to use a qualified name for the dependency that should be injected, +you should use the `@Named` annotation as follows: [source,java,indent=0] [subs="verbatim,quotes"] @@ -5699,7 +5738,6 @@ follows: } // ... - } ---- @@ -5727,13 +5765,11 @@ Instead of `@Component`, `@javax.inject.Named` may be used as follows: } // ... - } ---- -It is very common to use `@Component` without -specifying a name for the component. `@Named` -can be used in a similar fashion: +It is very common to use `@Component` without specifying a name for the component. +`@Named` can be used in a similar fashion: [source,java,indent=0] [subs="verbatim,quotes"] @@ -5752,7 +5788,6 @@ can be used in a similar fashion: } // ... - } ---- @@ -5778,32 +5813,32 @@ When working with standard annotations, it is important to know that some signif features are not available as shown in the table below: [[annotations-comparison]] -.Spring annotations vs. standard annotations +.Spring component model elements vs. JSR-330 variants |=== | Spring| javax.inject.*| javax.inject restrictions / comments | @Autowired | @Inject -| @Inject has no 'required' attribute +| `@Inject` has no 'required' attribute; can be used with Java 8's `Optional` instead. | @Component | @Named -| - +| JSR-330 does not provide a composable model, just a way to identify named components. | @Scope("singleton") | @Singleton | The JSR-330 default scope is like Spring's `prototype`. However, in order to keep it consistent with Spring's general defaults, a JSR-330 bean declared in the Spring container is a `singleton` by default. In order to use a scope other than `singleton`, - you should use Spring's `@Scope` annotation. - -`javax.inject` also provides a -http://download.oracle.com/javaee/6/api/javax/inject/Scope.html[@Scope] annotation. -Nevertheless, this one is only intended to be used for creating your own annotations. + you should use Spring's `@Scope` annotation. `javax.inject` also provides a + http://download.oracle.com/javaee/6/api/javax/inject/Scope.html[@Scope] annotation. + Nevertheless, this one is only intended to be used for creating your own annotations. | @Qualifier -| @Named -| - +| @Qualifier / @Named +| `javax.inject.Qualifier` is just a meta-annotation for building custom qualifiers. + Concrete String qualifiers (like Spring's `@Qualifier` with a value) can be associated + through `javax.inject.Named`. | @Value | - @@ -5816,6 +5851,12 @@ Nevertheless, this one is only intended to be used for creating your own annotat | @Lazy | - | no equivalent + +| ObjectFactory +| Provider +| `javax.inject.Provider` is a direct alternative to Spring's `ObjectFactory`, + just with a shorter `get()` method name. It can also be used in combination with + Spring's `@Autowired` or with non-annotated constructors and setter methods. |===