3. The IoC container

As was discussed in the chapter introduction, the
org.springframework.beans.factory package provides basic
functionality for managing and manipulating beans, including in a
programmatic way. The org.springframework.context package
adds the ApplicationContext interface, which
extends the BeanFactory interface, in
addition to extending other interfaces to provide additional functionality
in a more application framework-oriented style. Many
people use the ApplicationContext in a
completely declarative fashion, not even creating it programmatically, but
instead relying on support classes such as
ContextLoader to automatically instantiate an
ApplicationContext as part of the normal
startup process of a J2EE web application.

To enhance BeanFactory functionality in a
more framework-oriented style the context package also provides the
following functionality:

Loading of multiple (hierarchical) contexts, allowing each to be focused on one particular layer, such as the web layer of an application, through the HierarchicalBeanFactory interface.

Event publication to beans implementing the ApplicationListener interface, through the use of the ApplicationEventPublisher interface.

3.13.1 Internationalization using
MessageSource

The ApplicationContext interface
extends an interface called MessageSource,
and therefore provides internationalization (i18n) functionality. Spring
also provides the interface
HierarchicalMessageSource, which can resolve
messages hierarchically. Together these interfaces provide the foundation
upon which Spring effects message resolution. The methods defined on these
interfaces include:

  • String getMessage(String code, Object[] args, String
    default, Locale loc)
    : The basic method used to retrieve a
    message from the MessageSource. When no
    message is found for the specified locale, the default message is
    used. Any arguments passed in become replacement values, using the
    MessageFormat functionality provided by
    the standard library.

  • String getMessage(String code, Object[] args, Locale
    loc)
    : Essentially the same as the previous method, but
    with one difference: no default message can be specified; if the
    message cannot be found, a
    NoSuchMessageException is thrown.

  • String getMessage(MessageSourceResolvable resolvable,
    Locale locale)
    : All properties used in the preceding
    methods are also wrapped in a class named
    MessageSourceResolvable, which you can
    use with this method.

When an ApplicationContext is loaded,
it automatically searches for a
MessageSource bean defined in the context.
The bean must have the name messageSource. If such a
bean is found, all calls to the preceding methods are delegated to the
message source. If no message source is found, the
ApplicationContext attempts to find a
parent containing a bean with the same name. If it does, it uses that bean
as the MessageSource. If the
ApplicationContext cannot find any source
for messages, an empty DelegatingMessageSource is
instantiated in order to be able to accept calls to the methods defined
above.

Spring provides two MessageSource
implementations, ResourceBundleMessageSource and
StaticMessageSource. Both implement
HierarchicalMessageSource in order to do
nested messaging. The StaticMessageSource is rarely
used but provides programmatic ways to add messages to the source. The
ResourceBundleMessageSource is shown in the
following example:

<

beans

> <

bean

id

=

"messageSource"

class

=

"org.springframework.context.support.ResourceBundleMessageSource"

> <

property

name

=

"basenames"

> <

list

> <

value

>format<

/value

> <

value

>exceptions<

/value

> <

value

>windows<

/value

> <

/list

> <

/property

> <

/bean

> <

/beans

>

In the example it is assumed you have three resource bundles defined
in your classpath called format,
exceptions and windows. Any request
to resolve a message will be handled in the JDK standard way of resolving
messages through ResourceBundles. For the purposes of the example, assume
the contents of two of the above resource bundle files are…

# in format.properties
message=Alligators rock!
# in exceptions.properties
argument.required=The 

'{0}'

argument is required.

A program to execute the MessageSource
functionality is shown in the next example. Remember that all
ApplicationContext implementations are also
MessageSource implementations and so can be cast to
the MessageSource interface.

public

static

void

main(String[] args) { MessageSource resources =

new

ClassPathXmlApplicationContext(

"beans.xml"

); String message = resources.getMessage(

"message"

, null,

"Default"

, null); System.out.println(message); }

The resulting output from the above program will be…

Alligators rock!

So to summarize, the MessageSource is defined
in a file called beans.xml, which exists at the root of
your classpath. The messageSource bean definition
refers to a number of resource bundles through its
basenames property. The three files that are passed in
the list to the basenames property exist as files at
the root of your classpath and are called
format.properties,
exceptions.properties, and
windows.properties respectively.

The next example shows arguments passed to the message lookup; these
arguments will be converted into Strings and inserted into placeholders in
the lookup message.

<

beans

> < > <

bean

id

=

"messageSource"

class

=

"org.springframework.context.support.ResourceBundleMessageSource"

> <

property

name

=

"basename"

value

=

"test-messages"

/> <

/bean

> < > <

bean

id

=

"example"

class

=

"com.foo.Example"

> <

property

name

=

"messages"

ref

=

"messageSource"

/> <

/bean

> <

/beans

>

public

class

Example {

private

MessageSource messages;

public

void

setMessages(MessageSource messages) {

this

.messages = messages; }

public

void

execute() { String message =

this

.messages.getMessage(

"argument.required"

,

new

Object [] {

"userDao"

},

"Required"

, null); System.out.println(message); } }

The resulting output from the invocation of the
execute() method will be…

The userDao argument is required.

With regard to internationalization (i18n), Spring’s various
MessageResource implementations follow the same
locale resolution and fallback rules as the standard JDK
ResourceBundle. In short, and continuing with the
example messageSource defined previously, if you want
to resolve messages against the British (en-GB) locale, you would create
files called format_en_GB.properties,
exceptions_en_GB.properties, and
windows_en_GB.properties respectively.

Typically, locale resolution is managed by the surrounding environment
of the application. In this example, the locale against which (British)
messages will be resolved is specified manually.

# in exceptions_en_GB.properties

argument.required=Ebagum lad, the '{0}' argument is required, I say, required.

public

static

void

main(

final

String[] args) { MessageSource resources =

new

ClassPathXmlApplicationContext(

"beans.xml"

); String message = resources.getMessage(

"argument.required"

,

new

Object [] {

"userDao"

},

"Required"

, Locale.UK); System.out.println(message); }

The resulting output from the running of the above program will
be…

Ebagum lad, the 'userDao' argument is required, I say, required.

You can also use the MessageSourceAware
interface to acquire a reference to any
MessageSource that has been defined. Any bean that
is defined in an ApplicationContext that implements
the MessageSourceAware interface is injected with
the application context’s MessageSource when the
bean is created and configured.

[Note]Note

As an alternative to
ResourceBundleMessageSource, Spring provides a
ReloadableResourceBundleMessageSource class. This
variant supports the same bundle file format but is more flexible than
the standard JDK based
ResourceBundleMessageSource
implementation. In particular, it allows for reading files
from any Spring resource location (not just from the classpath) and
supports hot reloading of bundle property files (while efficiently
caching them in between). Check out the
ReloadableResourceBundleMessageSource javadoc for
details.