Browse Source

Recommend ObjectProvider as alternative to @Lazy for optional dependencies

Closes gh-27649
pull/28694/head
Juergen Hoeller 4 years ago
parent
commit
f0de3a9924
  1. 7
      spring-context/src/main/java/org/springframework/context/annotation/Lazy.java
  2. 148
      src/docs/asciidoc/core/core-beans.adoc

7
spring-context/src/main/java/org/springframework/context/annotation/Lazy.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2021 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -47,6 +47,11 @@ import java.lang.annotation.Target;
* or {@link javax.inject.Inject}: In that context, it leads to the creation of a * or {@link javax.inject.Inject}: In that context, it leads to the creation of a
* lazy-resolution proxy for all affected dependencies, as an alternative to using * lazy-resolution proxy for all affected dependencies, as an alternative to using
* {@link org.springframework.beans.factory.ObjectFactory} or {@link javax.inject.Provider}. * {@link org.springframework.beans.factory.ObjectFactory} or {@link javax.inject.Provider}.
* Please note that such a lazy-resolution proxy will always be injected; if the target
* dependency does not exist, you will only be able to find out through an exception on
* invocation. As a consequence, such an injection point results in unintuitive behavior
* for optional dependencies. For a programmatic equivalent, allowing for lazy references
* with more sophistication, consider {@link org.springframework.beans.factory.ObjectProvider}.
* *
* @author Chris Beams * @author Chris Beams
* @author Juergen Hoeller * @author Juergen Hoeller

148
src/docs/asciidoc/core/core-beans.adoc

@ -1024,7 +1024,7 @@ by type without help. Consider the following class:
class ExampleBean( class ExampleBean(
private val years: Int, // Number of years to calculate the Ultimate Answer private val years: Int, // Number of years to calculate the Ultimate Answer
private val ultimateAnswer: String// The Answer to Life, the Universe, and Everything private val ultimateAnswer: String // The Answer to Life, the Universe, and Everything
) )
---- ----
@ -1608,7 +1608,7 @@ listings shows how to use the `parent` attribute:
---- ----
<!-- in the parent context --> <!-- in the parent context -->
<bean id="accountService" class="com.something.SimpleAccountService"> <bean id="accountService" class="com.something.SimpleAccountService">
<!-- insert dependencies as required as here --> <!-- insert dependencies as required here -->
</bean> </bean>
---- ----
@ -1690,7 +1690,7 @@ respectively. The following example shows how to use them:
<property name="someMap"> <property name="someMap">
<map> <map>
<entry key="an entry" value="just some string"/> <entry key="an entry" value="just some string"/>
<entry key ="a ref" value-ref="myDataSource"/> <entry key="a ref" value-ref="myDataSource"/>
</map> </map>
</property> </property>
<!-- results in a setSomeSet(java.util.Set) call --> <!-- results in a setSomeSet(java.util.Set) call -->
@ -1834,7 +1834,7 @@ class SomeClass {
When the `accounts` property of the `something` bean is prepared for injection, the generics When the `accounts` property of the `something` bean is prepared for injection, the generics
information about the element type of the strongly-typed `Map<String, Float>` is information about the element type of the strongly-typed `Map<String, Float>` is
available by reflection. Thus, Spring's type conversion infrastructure recognizes the available by reflection. Thus, Spring's type conversion infrastructure recognizes the
various value elements as being of type `Float`, and the string values (`9.99, 2.75`, and various value elements as being of type `Float`, and the string values (`9.99`, `2.75`, and
`3.99`) are converted into an actual `Float` type. `3.99`) are converted into an actual `Float` type.
@ -2028,7 +2028,7 @@ not commonly used since the plain order of declaration is usually sufficient the
In practice, the constructor resolution In practice, the constructor resolution
<<beans-factory-ctor-arguments-resolution,mechanism>> is quite efficient in matching <<beans-factory-ctor-arguments-resolution,mechanism>> is quite efficient in matching
arguments, so unless you really need to, we recommend using the name notation arguments, so unless you really need to, we recommend using the name notation
through-out your configuration. throughout your configuration.
[[beans-compound-property-names]] [[beans-compound-property-names]]
@ -2503,13 +2503,13 @@ declared return type of the lookup method:
public abstract class CommandManager { public abstract class CommandManager {
public Object process(Object commandState) { public Object process(Object commandState) {
MyCommand command = createCommand(); Command command = createCommand();
command.setState(commandState); command.setState(commandState);
return command.execute(); return command.execute();
} }
@Lookup @Lookup
protected abstract MyCommand createCommand(); protected abstract Command createCommand();
} }
---- ----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@ -2604,9 +2604,9 @@ interface provides the new method definition, as the following example shows:
.Kotlin .Kotlin
---- ----
/** /**
* meant to be used to override the existing computeValue(String) * meant to be used to override the existing computeValue(String)
* implementation in MyValueCalculator * implementation in MyValueCalculator
*/ */
class ReplacementComputeValue : MethodReplacer { class ReplacementComputeValue : MethodReplacer {
override fun reimplement(obj: Any, method: Method, args: Array<out Any>): Any { override fun reimplement(obj: Any, method: Method, args: Array<out Any>): Any {
@ -2806,7 +2806,7 @@ prototype-scoped bean repeatedly at runtime. You cannot dependency-inject a
prototype-scoped bean into your singleton bean, because that injection occurs only prototype-scoped bean into your singleton bean, because that injection occurs only
once, when the Spring container instantiates the singleton bean and resolves once, when the Spring container instantiates the singleton bean and resolves
and injects its dependencies. If you need a new instance of a prototype bean at and injects its dependencies. If you need a new instance of a prototype bean at
runtime more than once, see <<beans-factory-method-injection>> runtime more than once, see <<beans-factory-method-injection>>.
@ -2984,7 +2984,7 @@ The Spring container creates a new instance of the `AppPreferences` bean by usin
`appPreferences` bean is scoped at the `ServletContext` level and stored as a regular `appPreferences` bean is scoped at the `ServletContext` level and stored as a regular
`ServletContext` attribute. This is somewhat similar to a Spring singleton bean but `ServletContext` attribute. This is somewhat similar to a Spring singleton bean but
differs in two important ways: It is a singleton per `ServletContext`, not per Spring differs in two important ways: It is a singleton per `ServletContext`, not per Spring
'ApplicationContext' (for which there may be several in any given web application), `ApplicationContext` (for which there may be several in any given web application),
and it is actually exposed and therefore visible as a `ServletContext` attribute. and it is actually exposed and therefore visible as a `ServletContext` attribute.
When using annotation-driven components or Java configuration, you can use the When using annotation-driven components or Java configuration, you can use the
@ -3039,7 +3039,7 @@ constructor or setter argument or autowired field) as `ObjectFactory<MyTargetBea
allowing for a `getObject()` call to retrieve the current instance on demand every 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. time it is needed -- without holding on to the instance or storing it separately.
As an extended variant, you may declare `ObjectProvider<MyTargetBean>`, which delivers As an extended variant, you may declare `ObjectProvider<MyTargetBean>` which delivers
several additional access variants, including `getIfAvailable` and `getIfUnique`. several additional access variants, including `getIfAvailable` and `getIfUnique`.
The JSR-330 variant of this is called `Provider` and is used with a `Provider<MyTargetBean>` The JSR-330 variant of this is called `Provider` and is used with a `Provider<MyTargetBean>`
@ -3100,7 +3100,7 @@ to the HTTP `Session`-scoped bean (`userPreferences`). The salient point here is
`userManager` bean is a singleton: it is instantiated exactly once per `userManager` bean is a singleton: it is instantiated exactly once per
container, and its dependencies (in this case only one, the `userPreferences` bean) are container, and its dependencies (in this case only one, the `userPreferences` bean) are
also injected only once. This means that the `userManager` bean operates only on the also injected only once. This means that the `userManager` bean operates only on the
exact same `userPreferences` object (that is, the one with which it was originally injected. exact same `userPreferences` object (that is, the one with which it was originally injected).
This is not the behavior you want when injecting a shorter-lived scoped bean into a This is not the behavior you want when injecting a shorter-lived scoped bean into a
longer-lived scoped bean (for example, injecting an HTTP `Session`-scoped collaborating longer-lived scoped bean (for example, injecting an HTTP `Session`-scoped collaborating
@ -3350,8 +3350,9 @@ of the scope. You can also do the `Scope` registration declaratively, by using t
</beans> </beans>
---- ----
NOTE: When you place `<aop:scoped-proxy/>` in a `FactoryBean` implementation, it is the factory NOTE: When you place `<aop:scoped-proxy/>` within a `<bean>` declaration for a
bean itself that is scoped, not the object returned from `getObject()`. `FactoryBean` implementation, it is the factory bean itself that is scoped, not the object
returned from `getObject()`.
@ -3927,7 +3928,7 @@ shows the definition of the BeanNameAware interface:
---- ----
The callback is invoked after population of normal bean properties but before an The callback is invoked after population of normal bean properties but before an
initialization callback such as `InitializingBean`, `afterPropertiesSet`, or a custom initialization callback such as `InitializingBean.afterPropertiesSet()` or a custom
init-method. init-method.
@ -3959,7 +3960,7 @@ dependency type. The following table summarizes the most important `Aware` inter
| `BeanFactoryAware` | `BeanFactoryAware`
| Declaring `BeanFactory`. | Declaring `BeanFactory`.
| <<beans-factory-aware>> | <<beans-beanfactory>>
| `BeanNameAware` | `BeanNameAware`
| Name of the declaring bean. | Name of the declaring bean.
@ -4146,7 +4147,7 @@ or it may wrap a bean with a proxy. Some Spring AOP infrastructure classes are
implemented as bean post-processors in order to provide proxy-wrapping logic. implemented as bean post-processors in order to provide proxy-wrapping logic.
An `ApplicationContext` automatically detects any beans that are defined in the An `ApplicationContext` automatically detects any beans that are defined in the
configuration metadata that implements the `BeanPostProcessor` interface. The configuration metadata that implement the `BeanPostProcessor` interface. The
`ApplicationContext` registers these beans as post-processors so that they can be called `ApplicationContext` registers these beans as post-processors so that they can be called
later, upon bean creation. Bean post-processors can be deployed in the container in the later, upon bean creation. Bean post-processors can be deployed in the container in the
same fashion as any other beans. same fashion as any other beans.
@ -4544,22 +4545,22 @@ Java as opposed to a (potentially) verbose amount of XML, you can create your ow
`FactoryBean`, write the complex initialization inside that class, and then plug your `FactoryBean`, write the complex initialization inside that class, and then plug your
custom `FactoryBean` into the container. custom `FactoryBean` into the container.
The `FactoryBean` interface provides three methods: The `FactoryBean<T>` interface provides three methods:
* `Object getObject()`: Returns an instance of the object this factory creates. The * `T getObject()`: Returns an instance of the object this factory creates. The
instance can possibly be shared, depending on whether this factory returns singletons instance can possibly be shared, depending on whether this factory returns singletons
or prototypes. or prototypes.
* `boolean isSingleton()`: Returns `true` if this `FactoryBean` returns singletons or * `boolean isSingleton()`: Returns `true` if this `FactoryBean` returns singletons or
`false` otherwise. `false` otherwise. The default implementation of this method returns `true`.
* `Class getObjectType()`: Returns the object type returned by the `getObject()` method * `Class<?> getObjectType()`: Returns the object type returned by the `getObject()` method
or `null` if the type is not known in advance. or `null` if the type is not known in advance.
The `FactoryBean` concept and interface is used in a number of places within the Spring The `FactoryBean` concept and interface are used in a number of places within the Spring
Framework. More than 50 implementations of the `FactoryBean` interface ship with Spring Framework. More than 50 implementations of the `FactoryBean` interface ship with Spring
itself. itself.
When you need to ask a container for an actual `FactoryBean` instance itself instead of When you need to ask a container for an actual `FactoryBean` instance itself instead of
the bean it produces, preface the bean's `id` with the ampersand symbol (`&`) when the bean it produces, prefix the bean's `id` with the ampersand symbol (`&`) when
calling the `getBean()` method of the `ApplicationContext`. So, for a given `FactoryBean` calling the `getBean()` method of the `ApplicationContext`. So, for a given `FactoryBean`
with an `id` of `myBean`, invoking `getBean("myBean")` on the container returns the with an `id` of `myBean`, invoking `getBean("myBean")` on the container returns the
product of the `FactoryBean`, whereas invoking `getBean("&myBean")` returns the product of the `FactoryBean`, whereas invoking `getBean("&myBean")` returns the
@ -4677,11 +4678,11 @@ example:
---- ----
class SimpleMovieLister { class SimpleMovieLister {
@Required @Required
lateinit var movieFinder: MovieFinder lateinit var movieFinder: MovieFinder
// ... // ...
} }
---- ----
This annotation indicates that the affected bean property must be populated at This annotation indicates that the affected bean property must be populated at
@ -5377,7 +5378,7 @@ Letting qualifier values select against target bean names, within the type-match
candidates, does not require a `@Qualifier` annotation at the injection point. candidates, does not require a `@Qualifier` annotation at the injection point.
If there is no other resolution indicator (such as a qualifier or a primary marker), If there is no other resolution indicator (such as a qualifier or a primary marker),
for a non-unique dependency situation, Spring matches the injection point name for a non-unique dependency situation, Spring matches the injection point name
(that is, the field name or parameter name) against the target bean names and choose the (that is, the field name or parameter name) against the target bean names and chooses the
same-named candidate, if any. same-named candidate, if any.
==== ====
@ -5392,7 +5393,7 @@ matching an `account` qualifier against beans marked with the same qualifier lab
For beans that are themselves defined as a collection, `Map`, or array type, `@Resource` For beans that are themselves defined as a collection, `Map`, or array type, `@Resource`
is a fine solution, referring to the specific collection or array bean by unique name. is a fine solution, referring to the specific collection or array bean by unique name.
That said, as of 4.3, collection, you can match `Map`, and array types through Spring's That said, as of 4.3, you can match collection, `Map`, and array types through Spring's
`@Autowired` type matching algorithm as well, as long as the element type information `@Autowired` type matching algorithm as well, as long as the element type information
is preserved in `@Bean` return type signatures or collection inheritance hierarchies. is preserved in `@Bean` return type signatures or collection inheritance hierarchies.
In this case, you can use qualifier values to select among same-typed collections, In this case, you can use qualifier values to select among same-typed collections,
@ -6046,14 +6047,14 @@ example shows:
[source,java,indent=0,subs="verbatim,quotes",role="primary"] [source,java,indent=0,subs="verbatim,quotes",role="primary"]
.Java .Java
---- ----
@Configuration @Configuration
public class AppConfig { public class AppConfig {
@Bean @Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() { public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer(); return new PropertySourcesPlaceholderConfigurer();
} }
} }
---- ----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
@ -6079,7 +6080,7 @@ will get properties from `application.properties` and `application.yml` files.
Built-in converter support provided by Spring allows simple type conversion (to `Integer` Built-in converter support provided by Spring allows simple type conversion (to `Integer`
or `int` for example) to be automatically handled. Multiple comma-separated values can be or `int` for example) to be automatically handled. Multiple comma-separated values can be
automatically converted to String array without extra effort. automatically converted to `String` array without extra effort.
It is possible to provide a default value as following: It is possible to provide a default value as following:
@ -6103,8 +6104,8 @@ It is possible to provide a default value as following:
class MovieRecommender(@Value("\${catalog.name:defaultCatalog}") private val catalog: String) class MovieRecommender(@Value("\${catalog.name:defaultCatalog}") private val catalog: String)
---- ----
A Spring `BeanPostProcessor` uses a `ConversionService` behind the scene to handle the A Spring `BeanPostProcessor` uses a `ConversionService` behind the scenes to handle the
process for converting the String value in `@Value` to the target type. If you want to process for converting the `String` value in `@Value` to the target type. If you want to
provide conversion support for your own custom type, you can provide your own provide conversion support for your own custom type, you can provide your own
`ConversionService` bean instance as the following example shows: `ConversionService` bean instance as the following example shows:
@ -6130,7 +6131,7 @@ provide conversion support for your own custom type, you can provide your own
@Bean @Bean
fun conversionService(): ConversionService { fun conversionService(): ConversionService {
return DefaultFormattingConversionService().apply { return DefaultFormattingConversionService().apply {
addConverter(MyCustomConverter()) addConverter(MyCustomConverter())
} }
} }
@ -6319,7 +6320,7 @@ is meta-annotated with `@Component`, as the following example shows:
// ... // ...
} }
---- ----
<1> The `Component` causes `@Service` to be treated in the same way as `@Component`. <1> The `@Component` causes `@Service` to be treated in the same way as `@Component`.
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
.Kotlin .Kotlin
@ -6333,7 +6334,7 @@ is meta-annotated with `@Component`, as the following example shows:
// ... // ...
} }
---- ----
<1> The `Component` causes `@Service` to be treated in the same way as `@Component`. <1> The `@Component` causes `@Service` to be treated in the same way as `@Component`.
You can also combine meta-annotations to create "`composed annotations`". For example, You can also combine meta-annotations to create "`composed annotations`". For example,
the `@RestController` annotation from Spring MVC is composed of `@Controller` and the `@RestController` annotation from Spring MVC is composed of `@Controller` and
@ -6595,7 +6596,7 @@ and using "`stub`" repositories instead:
includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"), includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),
excludeFilters = @Filter(Repository.class)) excludeFilters = @Filter(Repository.class))
public class AppConfig { public class AppConfig {
... // ...
} }
---- ----
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
@ -6679,9 +6680,11 @@ factory method and other bean definition properties, such as a qualifier value t
the `@Qualifier` annotation. Other method-level annotations that can be specified are the `@Qualifier` annotation. Other method-level annotations that can be specified are
`@Scope`, `@Lazy`, and custom qualifier annotations. `@Scope`, `@Lazy`, and custom qualifier annotations.
TIP: In addition to its role for component initialization, you can also place the `@Lazy` annotation TIP: In addition to its role for component initialization, you can also place the `@Lazy`
on injection points marked with `@Autowired` or `@Inject`. In this context, it annotation on injection points marked with `@Autowired` or `@Inject`. In this context,
leads to the injection of a lazy-resolution proxy. it leads to the injection of a lazy-resolution proxy. However, such a proxy approach
is rather limited. For sophisticated lazy interactions, in particular in combination
with optional dependencies, we recommend `ObjectProvider<MyTargetBean>` instead.
Autowired fields and methods are supported, as previously discussed, with additional Autowired fields and methods are supported, as previously discussed, with additional
support for autowiring of `@Bean` methods. The following example shows how to do so: support for autowiring of `@Bean` methods. The following example shows how to do so:
@ -7161,7 +7164,7 @@ configuration, as shown in the following example:
With Gradle 4.6 and later, the dependency should be declared in the `annotationProcessor` With Gradle 4.6 and later, the dependency should be declared in the `annotationProcessor`
configuration, as shown in the following example: configuration, as shown in the following example:
[source,groovy,indent=0subs="verbatim,quotes,attributes"] [source,groovy,indent=0,subs="verbatim,quotes,attributes"]
---- ----
dependencies { dependencies {
annotationProcessor "org.springframework:spring-context-indexer:{spring-version}" annotationProcessor "org.springframework:spring-context-indexer:{spring-version}"
@ -7179,8 +7182,8 @@ TIP: The index is enabled automatically when a `META-INF/spring.components` file
on the classpath. If an index is partially available for some libraries (or use cases) on the classpath. If an index is partially available for some libraries (or use cases)
but could not be built for the whole application, you can fall back to a regular classpath but could not be built for the whole application, you can fall back to a regular classpath
arrangement (as though no index were present at all) by setting `spring.index.ignore` to arrangement (as though no index were present at all) by setting `spring.index.ignore` to
`true`, either as a JVM system property or in a `spring.properties` file at the root of `true`, either as a JVM system property or via the
the classpath. <<appendix.adoc#appendix-spring-properties,`SpringProperties`>> mechanism.
@ -7635,7 +7638,7 @@ to reduce subtle bugs that can be hard to track down when operating in "`lite`"
**** ****
The `@Bean` and `@Configuration` annotations are discussed in depth in the following sections. The `@Bean` and `@Configuration` annotations are discussed in depth in the following sections.
First, however, we cover the various ways of creating a spring container using by First, however, we cover the various ways of creating a spring container by using
Java-based configuration. Java-based configuration.
@ -7762,7 +7765,7 @@ To enable component scanning, you can annotate your `@Configuration` class as fo
@Configuration @Configuration
@ComponentScan(basePackages = "com.acme") // <1> @ComponentScan(basePackages = "com.acme") // <1>
public class AppConfig { public class AppConfig {
... // ...
} }
---- ----
<1> This annotation enables component scanning. <1> This annotation enables component scanning.
@ -7896,6 +7899,7 @@ init-param):
`@Bean` is a method-level annotation and a direct analog of the XML `<bean/>` element. `@Bean` is a method-level annotation and a direct analog of the XML `<bean/>` element.
The annotation supports some of the attributes offered by `<bean/>`, such as: The annotation supports some of the attributes offered by `<bean/>`, such as:
* <<beans-factory-lifecycle-initializingbean, init-method>> * <<beans-factory-lifecycle-initializingbean, init-method>>
* <<beans-factory-lifecycle-disposablebean, destroy-method>> * <<beans-factory-lifecycle-disposablebean, destroy-method>>
* <<beans-factory-autowire,autowiring>> * <<beans-factory-autowire,autowiring>>
@ -7984,7 +7988,7 @@ return type, as the following example shows:
However, this limits the visibility for advance type prediction to the specified However, this limits the visibility for advance type prediction to the specified
interface type (`TransferService`). Then, with the full type (`TransferServiceImpl`) interface type (`TransferService`). Then, with the full type (`TransferServiceImpl`)
known to the container only once, the affected singleton bean has been instantiated. known to the container only once the affected singleton bean has been instantiated.
Non-lazy singleton beans get instantiated according to their declaration order, Non-lazy singleton beans get instantiated according to their declaration order,
so you may see different type matching results depending on when another component so you may see different type matching results depending on when another component
tries to match by a non-declared type (such as `@Autowired TransferServiceImpl`, tries to match by a non-declared type (such as `@Autowired TransferServiceImpl`,
@ -8242,8 +8246,10 @@ Spring offers a convenient way of working with scoped dependencies through
<<beans-factory-scopes-other-injection, scoped proxies>>. The easiest way to create <<beans-factory-scopes-other-injection, scoped proxies>>. The easiest way to create
such a proxy when using the XML configuration is the `<aop:scoped-proxy/>` element. such a proxy when using the XML configuration is the `<aop:scoped-proxy/>` element.
Configuring your beans in Java with a `@Scope` annotation offers equivalent support Configuring your beans in Java with a `@Scope` annotation offers equivalent support
with the `proxyMode` attribute. The default is no proxy (`ScopedProxyMode.NO`), with the `proxyMode` attribute. The default is `ScopedProxyMode.DEFAULT`, which
but you can specify `ScopedProxyMode.TARGET_CLASS` or `ScopedProxyMode.INTERFACES`. typically indicates that no scoped proxy should be created unless a different default
has been configured at the component-scan instruction level. You can specify
`ScopedProxyMode.TARGET_CLASS`, `ScopedProxyMode.INTERFACES` or `ScopedProxyMode.NO`.
If you port the scoped proxy example from the XML reference documentation (see If you port the scoped proxy example from the XML reference documentation (see
<<beans-factory-scopes-other-injection, scoped proxies>>) to our `@Bean` using Java, <<beans-factory-scopes-other-injection, scoped proxies>>) to our `@Bean` using Java,
@ -8297,7 +8303,7 @@ as the following example shows:
@Configuration @Configuration
public class AppConfig { public class AppConfig {
@Bean(name = "myThing") @Bean("myThing")
public Thing thing() { public Thing thing() {
return new Thing(); return new Thing();
} }
@ -8390,7 +8396,7 @@ annotation, as the following example shows:
=== Using the `@Configuration` annotation === Using the `@Configuration` annotation
`@Configuration` is a class-level annotation indicating that an object is a source of `@Configuration` is a class-level annotation indicating that an object is a source of
bean definitions. `@Configuration` classes declare beans through public `@Bean` annotated bean definitions. `@Configuration` classes declare beans through `@Bean`-annotated
methods. Calls to `@Bean` methods on `@Configuration` classes can also be used to define methods. Calls to `@Bean` methods on `@Configuration` classes can also be used to define
inter-bean dependencies. See <<beans-java-basic-concepts>> for a general introduction. inter-bean dependencies. See <<beans-java-basic-concepts>> for a general introduction.
@ -9139,7 +9145,7 @@ method that returns `true` or `false`. For example, the following listing shows
val attrs = metadata.getAllAnnotationAttributes(Profile::class.java.name) val attrs = metadata.getAllAnnotationAttributes(Profile::class.java.name)
if (attrs != null) { if (attrs != null) {
for (value in attrs["value"]!!) { for (value in attrs["value"]!!) {
if (context.environment.acceptsProfiles(Profiles .of(*value as Array<String>))) { if (context.environment.acceptsProfiles(Profiles.of(*value as Array<String>))) {
return true return true
} }
} }
@ -9903,7 +9909,7 @@ as a way to provide a default definition for one or more beans. If any
profile is enabled, the default profile does not apply. profile is enabled, the default profile does not apply.
You can change the name of the default profile by using `setDefaultProfiles()` on You can change the name of the default profile by using `setDefaultProfiles()` on
the `Environment` or ,declaratively, by using the `spring.profiles.default` property. the `Environment` or, declaratively, by using the `spring.profiles.default` property.
@ -10222,8 +10228,8 @@ bean with the same name. If it does, it uses that bean as the `MessageSource`. I
`DelegatingMessageSource` is instantiated in order to be able to accept calls to the `DelegatingMessageSource` is instantiated in order to be able to accept calls to the
methods defined above. methods defined above.
Spring provides two `MessageSource` implementations, `ResourceBundleMessageSource` and Spring provides three `MessageSource` implementations, `ResourceBundleMessageSource`, `ReloadableResourceBundleMessageSource`
`StaticMessageSource`. Both implement `HierarchicalMessageSource` in order to do nested and `StaticMessageSource`. All of them implement `HierarchicalMessageSource` in order to do nested
messaging. The `StaticMessageSource` is rarely used but provides programmatic ways to messaging. The `StaticMessageSource` is rarely used but provides programmatic ways to
add messages to the source. The following example shows `ResourceBundleMessageSource`: add messages to the source. The following example shows `ResourceBundleMessageSource`:
@ -10408,6 +10414,10 @@ You can also use the `MessageSourceAware` interface to acquire a reference to an
`ApplicationContext` that implements the `MessageSourceAware` interface is injected with `ApplicationContext` that implements the `MessageSourceAware` interface is injected with
the application context's `MessageSource` when the bean is created and configured. the application context's `MessageSource` when the bean is created and configured.
NOTE: Because Spring's `MessageSource` is based on Java's `ResourceBundle`, it does not merge
bundles with the same base name, but will only use the first bundle found.
Subsequent message bundles with the same base name are ignored.
NOTE: As an alternative to `ResourceBundleMessageSource`, Spring provides a NOTE: As an alternative to `ResourceBundleMessageSource`, Spring provides a
`ReloadableResourceBundleMessageSource` class. This variant supports the same bundle `ReloadableResourceBundleMessageSource` class. This variant supports the same bundle
file format but is more flexible than the standard JDK based file format but is more flexible than the standard JDK based
@ -10718,7 +10728,7 @@ following example shows how to do so:
---- ----
It is also possible to add additional runtime filtering by using the `condition` attribute It is also possible to add additional runtime filtering by using the `condition` attribute
of the annotation that defines a <<expressions, `SpEL` expression>> , which should match of the annotation that defines a <<expressions, `SpEL` expression>>, which should match
to actually invoke the method for a particular event. to actually invoke the method for a particular event.
The following example shows how our notifier can be rewritten to be invoked only if the The following example shows how our notifier can be rewritten to be invoked only if the
@ -10830,10 +10840,12 @@ The following example shows how to do so:
Be aware of the following limitations when using asynchronous events: Be aware of the following limitations when using asynchronous events:
* If an asynchronous event listener throws an `Exception`, it is not propagated to the * If an asynchronous event listener throws an `Exception`, it is not propagated to the
caller. See `AsyncUncaughtExceptionHandler` for more details. caller. See
{api-spring-framework}/aop/interceptor/AsyncUncaughtExceptionHandler.html[`AsyncUncaughtExceptionHandler`]
for more details.
* Asynchronous event listener methods cannot publish a subsequent event by returning a * Asynchronous event listener methods cannot publish a subsequent event by returning a
value. If you need to publish another event as the result of the processing, inject an value. If you need to publish another event as the result of the processing, inject an
{api-spring-framework}/aop/interceptor/AsyncUncaughtExceptionHandler.html[`ApplicationEventPublisher`] {api-spring-framework}/context/ApplicationEventPublisher.html[`ApplicationEventPublisher`]
to publish the event manually. to publish the event manually.
@ -11021,8 +11033,8 @@ For a simple deployment of a Spring ApplicationContext as a Java EE RAR file:
. Package . Package
all application classes into a RAR file (which is a standard JAR file with a different all application classes into a RAR file (which is a standard JAR file with a different
file extension). file extension).
.Add all required library JARs into the root of the RAR archive. . Add all required library JARs into the root of the RAR archive.
.Add a . Add a
`META-INF/ra.xml` deployment descriptor (as shown in the {api-spring-framework}/jca/context/SpringContextResourceAdapter.html[javadoc for `SpringContextResourceAdapter`]) `META-INF/ra.xml` deployment descriptor (as shown in the {api-spring-framework}/jca/context/SpringContextResourceAdapter.html[javadoc for `SpringContextResourceAdapter`])
and the corresponding Spring XML bean definition file(s) (typically and the corresponding Spring XML bean definition file(s) (typically
`META-INF/applicationContext.xml`). `META-INF/applicationContext.xml`).
@ -11116,7 +11128,7 @@ The following table lists features provided by the `BeanFactory` and
| No | No
| Yes | Yes
| Convenient `MessageSource` access (for internalization) | Convenient `MessageSource` access (for internationalization)
| No | No
| Yes | Yes

Loading…
Cancel
Save