Document @Bean 'lite' mode vs @Configuration

Rework the reference documentation to better distinguish the differences
between @Bean methods used in @Comonent vs @Configuration classes. The
'Using the @Bean annotation' section now only covers concepts applicable
when using @Bean methods in @Configuration _or_ @Component classes.
Information only applicable to @Configuration classes has been moved to
a new  'Using the @Configuration annotation' section.

An additional sidebar section attempts to explain the differences
between the two approaches.

Issue: SPR-9425
This commit is contained in:
Phillip Webb
2013-03-12 22:11:23 -07:00
parent 457ee07352
commit 5730b8d316

View File

@@ -10,21 +10,46 @@
<title>Java-based container configuration</title>
<section xml:id="beans-java-basic-concepts">
<title>Basic concepts: <literal>@Configuration</literal> and
<literal>@Bean</literal></title>
<title>Basic concepts: <literal>@Bean</literal> and <literal>@Configuration</literal></title>
<para>The central artifact in Spring's new Java-configuration support is the
<interfacename>@Configuration</interfacename>-annotated class. These
classes consist principally of
<interfacename>@Bean</interfacename>-annotated methods that define
instantiation, configuration, and initialization logic for objects to be
managed by the Spring IoC container.</para>
<sidebar>
<title>Full @Configuration vs 'lite' @Beans mode?</title>
<para>When <interfacename>@Bean</interfacename> methods are declared within
classes that are <emphasis>not</emphasis> annotated with
<interfacename>@Configuration</interfacename> they are referred to as being
processed in a 'lite' mode. For example, bean methods declared in a
<interfacename>@Component</interfacename> or even in a <emphasis>plain old
class</emphasis> will be considered 'lite'.</para>
<para>Unlike full <interfacename>@Configuration</interfacename>, lite
<interfacename>@Bean</interfacename> methods cannot easily declare inter-bean
dependencies. Usually one <interfacename>@Bean</interfacename> method should not
invoke another <interfacename>@Bean</interfacename> method when operating in
'lite' mode.</para>
<para>Only using <interfacename>@Bean</interfacename> methods within
<interfacename>@Configuration</interfacename> classes is a recommended approach
of ensuring that 'full' mode is always used. This will prevent the same
<interfacename>@Bean</interfacename> method from accidentally being invoked
multiple times and helps to reduce subtle bugs that can be hard to track down
when operating in 'lite' mode.</para>
</sidebar>
<para>Annotating a class with the
<interfacename>@Configuration</interfacename> indicates that the class can
be used by the Spring IoC container as a source of bean definitions. The
simplest possible <interfacename>@Configuration</interfacename> class
would read as follows:
<para>The central artifacts in Spring's new Java-configuration support are
<interfacename>@Configuration</interfacename>-annotated classes and
<interfacename>@Bean</interfacename>-annotated methods.</para>
<para>The <interfacename>@Bean</interfacename> annotation is used to indicate that a
method instantiates, configures and initializes a new object to be managed by
the Spring IoC container. For those familiar with Spring's
<literal>&lt;beans/&gt;</literal> XML configuration the <literal>@Bean</literal>
annotation plays the same role as the <literal>&lt;bean/&gt;</literal>
element. You can use <interfacename>@Bean</interfacename> annotated methods with
any Spring <interfacename>@Component</interfacename>, however, they are most
often used with <interfacename>@Configuration</interfacename> beans.</para>
<para>Annotating a class with <interfacename>@Configuration</interfacename>
indicates that its primary purpose is as a source of bean definitions. Furthermore,
<interfacename>@Configuration</interfacename> classes allow inter-bean
dependencies to be defined by simply calling other <interfacename>@Bean</interfacename>
methods in the same class. The simplest possible
<interfacename>@Configuration</interfacename> class would read as follows:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
@@ -33,16 +58,15 @@ public class AppConfig {
}
}</programlisting></para>
<para>For those more familiar with Spring <literal>&lt;beans/&gt;</literal>
XML, the <literal>AppConfig</literal> class above would be equivalent to:
<para>The <literal>AppConfig</literal> class above would be equivalent to the
following Spring <literal>&lt;beans/&gt;</literal> XML:
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="myService" class="com.acme.services.MyServiceImpl"/&gt;
&lt;/beans&gt;</programlisting>
As you can see, the <literal>@Bean</literal> annotation plays the same
role as the <literal>&lt;bean/&gt;</literal> element. The
<literal>@Bean</literal> annotation will be discussed in depth in the
sections below. First, however, we'll cover the various ways of creating a
spring container using Java-based configuration.</para>
The <interfacename>@Bean</interfacename> and <interfacename>@Configuration</interfacename>
annotations will be discussed in depth in the sections below. First, however, we'll
cover the various ways of creating a spring container using Java-based
configuration.</para>
</section>
<section xml:id="beans-java-instantiating-container">
@@ -218,6 +242,387 @@ public class AppConfig {
</section>
</section>
<section xml:id="beans-java-bean-annotation">
<title>Using the <interfacename>@Bean</interfacename> annotation</title>
<para><interfacename>@Bean</interfacename> is a method-level annotation and
a direct analog of the XML <code>&lt;bean/&gt;</code> element. The
annotation supports some of the attributes offered by
<code>&lt;bean/&gt;</code>, such as: <code><link
linkend="beans-factory-lifecycle-initializingbean"
>init-method</link></code>, <code><link
linkend="beans-factory-lifecycle-disposablebean"
>destroy-method</link></code>, <code><link
linkend="beans-factory-autowire">autowiring</link></code> and
<code>name</code>.</para>
<para>You can use the <interfacename>@Bean</interfacename> annotation in a
<interfacename>@Configuration</interfacename>-annotated or in a
<interfacename>@Component</interfacename>-annotated class.</para>
<section xml:id="beans-java-declaring-a-bean">
<title>Declaring a bean</title>
<para>To declare a bean, simply annotate a method with the
<interfacename>@Bean</interfacename> annotation. You use this method to
register a bean definition within an <code>ApplicationContext</code> of
the type specified as the method's return value. By default, the bean
name will be the same as the method name. The following is a simple
example of a <interfacename>@Bean</interfacename> method declaration:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}</programlisting></para>
<para>The preceding configuration is exactly equivalent to the following
Spring XML:
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="transferService" class="com.acme.TransferServiceImpl"/&gt;
&lt;/beans&gt; </programlisting></para>
<para>Both declarations make a bean named <code>transferService</code>
available in the <code>ApplicationContext</code>, bound to an object
instance of type <code>TransferServiceImpl</code>:
<programlisting>
transferService -&gt; com.acme.TransferServiceImpl
</programlisting></para>
</section>
<section xml:id="beans-java-lifecycle-callbacks">
<title>Receiving lifecycle callbacks</title>
<para>Any classes defined with the
<literal>@Bean</literal> annotation support
the regular lifecycle callbacks and can use the
<literal>@PostConstruct</literal> and <literal>@PreDestroy</literal>
annotations from JSR-250, see <link
linkend="beans-postconstruct-and-predestroy-annotations">JSR-250
annotations</link> for further details.</para>
<para>The regular Spring <link linkend="beans-factory-nature"
>lifecycle</link> callbacks are fully supported as well. If a bean
implements <code>InitializingBean</code>, <code>DisposableBean</code>,
or <code>Lifecycle</code>, their respective methods are called by the
container.</para>
<para>The standard set of <code>*Aware</code> interfaces such as
<code><link linkend="beans-beanfactory">BeanFactoryAware</link></code>,
<code><link linkend="beans-factory-aware">BeanNameAware</link></code>,
<code><link linkend="context-functionality-messagesource"
>MessageSourceAware</link></code>, <code><link
linkend="beans-factory-aware">ApplicationContextAware</link></code>, and
so on are also fully supported.</para>
<para>The <interfacename>@Bean</interfacename> annotation supports
specifying arbitrary initialization and destruction callback methods,
much like Spring XML's <code>init-method</code> and
<code>destroy-method</code> attributes on the <code>bean</code> element:
<programlisting language="java">public class Foo {
public void init() {
// initialization logic
}
}
public class Bar {
public void cleanup() {
// destruction logic
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
public Foo foo() {
return new Foo();
}
@Bean(destroyMethod = "cleanup")
public Bar bar() {
return new Bar();
}
}
</programlisting></para>
<para>Of course, in the case of <code>Foo</code> above, it would be
equally as valid to call the <code>init()</code> method directly during
construction:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public Foo foo() {
Foo foo = new Foo();
foo.init();
return foo;
}
// ...
} </programlisting></para>
<tip>
<para>When you work directly in Java, you can do anything you like with
your objects and do not always need to rely on the container
lifecycle!</para>
</tip>
</section>
<section xml:id="beans-java-specifying-bean-scope">
<title>Specifying bean scope</title>
<section xml:id="beans-java-available-scopes">
<title>Using the <interfacename>@Scope</interfacename>
annotation</title>
<!-- MLP: Beverly, did not apply your edit as it changed meaning -->
<para>You can specify that your beans defined with the
<interfacename>@Bean</interfacename> annotation should have a specific
scope. You can use any of the standard scopes specified in the <link
linkend="beans-factory-scopes">Bean Scopes</link> section.</para>
<para>The default scope is <literal>singleton</literal>, but you can
override this with the <interfacename>@Scope</interfacename>
annotation:
<programlisting language="java">@Configuration
public class MyConfiguration {
@Bean
<emphasis role="bold">@Scope("prototype")</emphasis>
public Encryptor encryptor() {
// ...
}
}</programlisting></para>
</section>
<section xml:id="beans-java-scoped-proxy">
<title><code>@Scope and scoped-proxy</code></title>
<para>Spring offers a convenient way of working with scoped dependencies
through <link linkend="beans-factory-scopes-other-injection">scoped
proxies</link>. The easiest way to create such a proxy when using the
XML configuration is the <code>&lt;aop:scoped-proxy/&gt;</code>
element. Configuring your beans in Java with a @Scope annotation
offers equivalent support with the proxyMode attribute. The default is
no proxy (<varname>ScopedProxyMode.NO</varname>), but you can specify
<classname>ScopedProxyMode.TARGET_CLASS</classname> or
<classname>ScopedProxyMode.INTERFACES</classname>.</para>
<para>If you port the scoped proxy example from the XML reference
documentation (see preceding link) to our
<interfacename>@Bean</interfacename> using Java, it would look like
the following:
<programlisting language="java">// an HTTP Session-scoped bean exposed as a proxy
@Bean
<emphasis role="bold">@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)</emphasis>
public UserPreferences userPreferences() {
return new UserPreferences();
}
@Bean
public Service userService() {
UserService service = new SimpleUserService();
// a reference to the proxied userPreferences bean
service.setUserPreferences(userPreferences());
return service;
} </programlisting></para>
</section>
</section>
<section xml:id="beans-java-customizing-bean-naming">
<title>Customizing bean naming</title>
<para>By default, configuration classes use a
<interfacename>@Bean</interfacename> method's name as the name of the
resulting bean. This functionality can be overridden, however, with the
<code>name</code> attribute.
<programlisting language="java">@Configuration
public class AppConfig {
@Bean(name = "myFoo")
public Foo foo() {
return new Foo();
}
} </programlisting></para>
</section>
<section xml:id="beans-java-bean-aliasing">
<title>Bean aliasing</title>
<para>As discussed in <xref linkend="beans-beanname"/>, it is sometimes
desirable to give a single bean multiple names, otherwise known as
<emphasis>bean aliasing</emphasis>. The <literal>name</literal>
attribute of the <literal>@Bean</literal> annotation accepts a String
array for this purpose.
<programlisting language="java">@Configuration
public class AppConfig {
@Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
public DataSource dataSource() {
// instantiate, configure and return DataSource bean...
}
} </programlisting></para>
</section>
</section>
<section xml:id="beans-java-configuration-annotation">
<title>Using the <interfacename>@Configuration</interfacename> annotation</title>
<para><interfacename>@Configuration</interfacename> is a class-level annotation
indicating that an object is a source of bean definitions.
<interfacename>@Configuration</interfacename> classes declare beans via
public <interfacename>@Bean</interfacename> annotated methods. Calls to
<interfacename>@Bean</interfacename> methods on
<interfacename>@Configuration</interfacename> classes can also be used to
define inter-bean dependencies. See <xref linkend="beans-java-basic-concepts"/> for
a general introduction.</para>
<section xml:id="beans-java-injecting-dependencies">
<title>Injecting inter-bean dependencies</title>
<para>When <interfacename>@Bean</interfacename>s have dependencies on one
another, expressing that dependency is as simple as having one bean
method call another:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public Foo foo() {
return new Foo(bar());
}
@Bean
public Bar bar() {
return new Bar();
}
} </programlisting></para>
<para>In the example above, the <code>foo</code> bean receives a reference
to <code> bar</code> via constructor injection.</para>
<note>
<para>This method of declaring inter-bean dependencies only works when
the <interfacename>@Bean</interfacename> method is declared within a
<interfacename>@Configuration</interfacename> class. You cannot declare
inter-bean dependencies using plain <interfacename>@Component</interfacename>
classes.</para>
</note>
</section>
<section xml:id="beans-java-method-injection">
<title>Lookup method injection</title>
<para>As noted earlier, <link linkend="beans-factory-method-injection"
>lookup method injection</link> is an advanced feature that you should
use rarely. It is useful in cases where a singleton-scoped bean has a
dependency on a prototype-scoped bean. Using Java for this type of
configuration provides a natural means for implementing this pattern.
<programlisting language="java">public abstract class CommandManager {
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();
}
// okay... but where is the implementation of this method?
protected abstract Command createCommand();
} </programlisting></para>
<para>Using Java-configuration support , you can create a subclass of
<code>CommandManager</code> where the abstract
<code>createCommand()</code> method is overridden in such a way that
it looks up a new (prototype) command object:
<programlisting language="java">@Bean
@Scope("prototype")
public AsyncCommand asyncCommand() {
AsyncCommand command = new AsyncCommand();
// inject dependencies here as required
return command;
}
@Bean
public CommandManager commandManager() {
// return new anonymous implementation of CommandManager with command() overridden
// to return a new prototype Command object
return new CommandManager() {
protected Command createCommand() {
return asyncCommand();
}
}
} </programlisting></para>
</section>
<section xml:id="beans-java-further-information-java-config">
<title>Further information about how Java-based configuration works
internally</title>
<para>The following example shows a <literal>@Bean</literal> annotated
method being called twice:</para>
<programlisting language="java">
@Configuration
public class AppConfig {
@Bean
public ClientService clientService1() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
</programlisting>
<para> <methodname>clientDao()</methodname> has been called once in
<methodname>clientService1()</methodname> and once in
<methodname>clientService2()</methodname>. Since this method creates a new
instance of <classname>ClientDaoImpl</classname> and returns it, you would
normally expect having 2 instances (one for each service). That definitely
would be problematic: in Spring, instantiated beans have a
<literal>singleton</literal> scope by default. This is where the magic
comes in: All <literal>@Configuration</literal> classes are subclassed at
startup-time with <literal>CGLIB</literal>. In the subclass, the child
method checks the container first for any cached (scoped) beans before it
calls the parent method and creates a new instance. Note that as of Spring
3.2, it is no longer necessary to add CGLIB to your classpath because
CGLIB classes have been repackaged under org.springframework and included
directly within the spring-core JAR.</para>
<note>
<para> The behavior could be different according to the scope of your
bean. We are talking about singletons here. </para>
</note>
<note>
<para> There are a few restrictions due to the fact that CGLIB dynamically
adds features at startup-time: <itemizedlist>
<listitem>
<para>Configuration classes should not be final</para>
</listitem>
<listitem>
<para>They should have a constructor with no arguments</para>
</listitem>
</itemizedlist> </para>
</note>
</section>
</section>
<section xml:id="beans-java-composing-configuration-classes">
<title>Composing Java-based configurations</title>
@@ -547,366 +952,4 @@ jdbc.password=</programlisting>
</section>
</section>
</section>
<section xml:id="beans-java-bean-annotation">
<title>Using the <interfacename>@Bean</interfacename> annotation</title>
<para><interfacename>@Bean</interfacename> is a method-level annotation and
a direct analog of the XML <code>&lt;bean/&gt;</code> element. The
annotation supports some of the attributes offered by
<code>&lt;bean/&gt;</code>, such as: <code><link
linkend="beans-factory-lifecycle-initializingbean"
>init-method</link></code>, <code><link
linkend="beans-factory-lifecycle-disposablebean"
>destroy-method</link></code>, <code><link
linkend="beans-factory-autowire">autowiring</link></code> and
<code>name</code>.</para>
<para>You can use the <interfacename>@Bean</interfacename> annotation in a
<interfacename>@Configuration</interfacename>-annotated or in a
<interfacename>@Component</interfacename>-annotated class.</para>
<section xml:id="beans-java-declaring-a-bean">
<title>Declaring a bean</title>
<para>To declare a bean, simply annotate a method with the
<interfacename>@Bean</interfacename> annotation. You use this method to
register a bean definition within an <code>ApplicationContext</code> of
the type specified as the method's return value. By default, the bean
name will be the same as the method name. The following is a simple
example of a <interfacename>@Bean</interfacename> method declaration:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}</programlisting></para>
<para>The preceding configuration is exactly equivalent to the following
Spring XML:
<programlisting language="xml">&lt;beans&gt;
&lt;bean id="transferService" class="com.acme.TransferServiceImpl"/&gt;
&lt;/beans&gt; </programlisting></para>
<para>Both declarations make a bean named <code>transferService</code>
available in the <code>ApplicationContext</code>, bound to an object
instance of type <code>TransferServiceImpl</code>:
<programlisting>
transferService -&gt; com.acme.TransferServiceImpl
</programlisting></para>
</section>
<section xml:id="beans-java-injecting-dependencies">
<title>Injecting dependencies</title>
<para>When <interfacename>@Bean</interfacename>s have dependencies on one
another, expressing that dependency is as simple as having one bean
method call another:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public Foo foo() {
return new Foo(bar());
}
@Bean
public Bar bar() {
return new Bar();
}
} </programlisting></para>
<para>In the example above, the <code>foo</code> bean receives a reference
to <code> bar</code> via constructor injection.</para>
</section>
<section xml:id="beans-java-lifecycle-callbacks">
<title>Receiving lifecycle callbacks</title>
<para>Beans declared in a
<interfacename>@Configuration</interfacename>-annotated class support
the regular lifecycle callbacks. Any classes defined with the
<literal>@Bean</literal> annotation can use the
<literal>@PostConstruct</literal> and <literal>@PreDestroy</literal>
annotations from JSR-250, see <link
linkend="beans-postconstruct-and-predestroy-annotations">JSR-250
annotations</link> for further details.</para>
<para>The regular Spring <link linkend="beans-factory-nature"
>lifecycle</link> callbacks are fully supported as well. If a bean
implements <code>InitializingBean</code>, <code>DisposableBean</code>,
or <code>Lifecycle</code>, their respective methods are called by the
container.</para>
<para>The standard set of <code>*Aware</code> interfaces such as
<code><link linkend="beans-beanfactory">BeanFactoryAware</link></code>,
<code><link linkend="beans-factory-aware">BeanNameAware</link></code>,
<code><link linkend="context-functionality-messagesource"
>MessageSourceAware</link></code>, <code><link
linkend="beans-factory-aware">ApplicationContextAware</link></code>, and
so on are also fully supported.</para>
<para>The <interfacename>@Bean</interfacename> annotation supports
specifying arbitrary initialization and destruction callback methods,
much like Spring XML's <code>init-method</code> and
<code>destroy-method</code> attributes on the <code>bean</code> element:
<programlisting language="java">public class Foo {
public void init() {
// initialization logic
}
}
public class Bar {
public void cleanup() {
// destruction logic
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init")
public Foo foo() {
return new Foo();
}
@Bean(destroyMethod = "cleanup")
public Bar bar() {
return new Bar();
}
}
</programlisting></para>
<para>Of course, in the case of <code>Foo</code> above, it would be
equally as valid to call the <code>init()</code> method directly during
construction:
<programlisting language="java">@Configuration
public class AppConfig {
@Bean
public Foo foo() {
Foo foo = new Foo();
foo.init();
return foo;
}
// ...
} </programlisting></para>
<tip>
<para>When you work directly in Java, you can do anything you like with
your objects and do not always need to rely on the container
lifecycle!</para>
</tip>
</section>
<section xml:id="beans-java-specifying-bean-scope">
<title>Specifying bean scope</title>
<section xml:id="beans-java-available-scopes">
<title>Using the <interfacename>@Scope</interfacename>
annotation</title>
<!-- MLP: Beverly, did not apply your edit as it changed meaning -->
<para>You can specify that your beans defined with the
<interfacename>@Bean</interfacename> annotation should have a specific
scope. You can use any of the standard scopes specified in the <link
linkend="beans-factory-scopes">Bean Scopes</link> section.</para>
<para>The default scope is <literal>singleton</literal>, but you can
override this with the <interfacename>@Scope</interfacename>
annotation:
<programlisting language="java">@Configuration
public class MyConfiguration {
@Bean
<emphasis role="bold">@Scope("prototype")</emphasis>
public Encryptor encryptor() {
// ...
}
}</programlisting></para>
</section>
<section xml:id="beans-java-scoped-proxy">
<title><code>@Scope and scoped-proxy</code></title>
<para>Spring offers a convenient way of working with scoped dependencies
through <link linkend="beans-factory-scopes-other-injection">scoped
proxies</link>. The easiest way to create such a proxy when using the
XML configuration is the <code>&lt;aop:scoped-proxy/&gt;</code>
element. Configuring your beans in Java with a @Scope annotation
offers equivalent support with the proxyMode attribute. The default is
no proxy (<varname>ScopedProxyMode.NO</varname>), but you can specify
<classname>ScopedProxyMode.TARGET_CLASS</classname> or
<classname>ScopedProxyMode.INTERFACES</classname>.</para>
<para>If you port the scoped proxy example from the XML reference
documentation (see preceding link) to our
<interfacename>@Bean</interfacename> using Java, it would look like
the following:
<programlisting language="java">// an HTTP Session-scoped bean exposed as a proxy
@Bean
<emphasis role="bold">@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)</emphasis>
public UserPreferences userPreferences() {
return new UserPreferences();
}
@Bean
public Service userService() {
UserService service = new SimpleUserService();
// a reference to the proxied userPreferences bean
service.setUserPreferences(userPreferences());
return service;
} </programlisting></para>
</section>
<section xml:id="beans-java-method-injection">
<title>Lookup method injection</title>
<para>As noted earlier, <link linkend="beans-factory-method-injection"
>lookup method injection</link> is an advanced feature that you should
use rarely. It is useful in cases where a singleton-scoped bean has a
dependency on a prototype-scoped bean. Using Java for this type of
configuration provides a natural means for implementing this pattern.
<programlisting language="java">public abstract class CommandManager {
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();
}
// okay... but where is the implementation of this method?
protected abstract Command createCommand();
} </programlisting></para>
<para>Using Java-configuration support , you can create a subclass of
<code>CommandManager</code> where the abstract
<code>createCommand()</code> method is overridden in such a way that
it looks up a new (prototype) command object:
<programlisting language="java">@Bean
@Scope("prototype")
public AsyncCommand asyncCommand() {
AsyncCommand command = new AsyncCommand();
// inject dependencies here as required
return command;
}
@Bean
public CommandManager commandManager() {
// return new anonymous implementation of CommandManager with command() overridden
// to return a new prototype Command object
return new CommandManager() {
protected Command createCommand() {
return asyncCommand();
}
}
} </programlisting></para>
</section>
</section>
<section xml:id="beans-java-customizing-bean-naming">
<title>Customizing bean naming</title>
<para>By default, configuration classes use a
<interfacename>@Bean</interfacename> method's name as the name of the
resulting bean. This functionality can be overridden, however, with the
<code>name</code> attribute.
<programlisting language="java">@Configuration
public class AppConfig {
@Bean(name = "myFoo")
public Foo foo() {
return new Foo();
}
} </programlisting></para>
</section>
<section xml:id="beans-java-bean-aliasing">
<title>Bean aliasing</title>
<para>As discussed in <xref linkend="beans-beanname"/>, it is sometimes
desirable to give a single bean multiple names, otherwise known as
<emphasis>bean aliasing</emphasis>. The <literal>name</literal>
attribute of the <literal>@Bean</literal> annotation accepts a String
array for this purpose.
<programlisting language="java">@Configuration
public class AppConfig {
@Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
public DataSource dataSource() {
// instantiate, configure and return DataSource bean...
}
} </programlisting></para>
</section>
</section>
<section xml:id="beans-java-further-information-java-config">
<title>Further information about how Java-based configuration works
internally</title>
<para>The following example shows a <literal>@Bean</literal> annotated
method being called twice:</para>
<programlisting language="java">
@Configuration
public class AppConfig {
@Bean
public ClientService clientService1() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
</programlisting>
<para> <methodname>clientDao()</methodname> has been called once in
<methodname>clientService1()</methodname> and once in
<methodname>clientService2()</methodname>. Since this method creates a new
instance of <classname>ClientDaoImpl</classname> and returns it, you would
normally expect having 2 instances (one for each service). That definitely
would be problematic: in Spring, instantiated beans have a
<literal>singleton</literal> scope by default. This is where the magic
comes in: All <literal>@Configuration</literal> classes are subclassed at
startup-time with <literal>CGLIB</literal>. In the subclass, the child
method checks the container first for any cached (scoped) beans before it
calls the parent method and creates a new instance. Note that as of Spring
3.2, it is no longer necessary to add CGLIB to your classpath because
CGLIB classes have been repackaged under org.springframework and included
directly within the spring-core JAR.</para>
<note>
<para> The behavior could be different according to the scope of your
bean. We are talking about singletons here. </para>
</note>
<note>
<para> There are a few restrictions due to the fact that CGLIB dynamically
adds features at startup-time: <itemizedlist>
<listitem>
<para>Configuration classes should not be final</para>
</listitem>
<listitem>
<para>They should have a constructor with no arguments</para>
</listitem>
</itemizedlist> </para>
</note>
</section>
</section>