public class ResourceBundleMessageSource extends AbstractResourceBasedMessageSource implements BeanClassLoaderAware
MessageSource
implementation that
accesses resource bundles using specified basenames. This class relies
on the underlying JDK's ResourceBundle
implementation,
in combination with the JDK's standard message parsing provided by
MessageFormat
.
This MessageSource caches both the accessed ResourceBundle instances and
the generated MessageFormats for each message. It also implements rendering of
no-arg messages without MessageFormat, as supported by the AbstractMessageSource
base class. The caching provided by this MessageSource is significantly faster
than the built-in caching of the java.util.ResourceBundle
class.
The basenames follow ResourceBundle
conventions: essentially,
a fully-qualified classpath location. If it doesn't contain a package qualifier
(such as org.mypackage
), it will be resolved from the classpath root.
Note that the JDK's standard ResourceBundle treats dots as package separators:
This means that "test.theme" is effectively equivalent to "test/theme".
On the classpath, bundle resources will be read with the locally configured
encoding
: by default, ISO-8859-1; consider switching
this to UTF-8, or to null
for the platform default encoding. On the JDK 9+
module path where locally provided ResourceBundle.Control
handles are not
supported, this MessageSource always falls back to ResourceBundle.getBundle(java.lang.String)
retrieval with the platform default encoding: UTF-8 with a ISO-8859-1 fallback on
JDK 9+ (configurable through the "java.util.PropertyResourceBundle.encoding" system
property). Note that loadBundle(Reader)
/loadBundle(InputStream)
won't be called in this case either, effectively ignoring overrides in subclasses.
Consider implementing a JDK 9 java.util.spi.ResourceBundleProvider
instead.
AbstractResourceBasedMessageSource.setBasenames(java.lang.String...)
,
ReloadableResourceBundleMessageSource
,
ResourceBundle
,
MessageFormat
logger
Constructor and Description |
---|
ResourceBundleMessageSource() |
Modifier and Type | Method and Description |
---|---|
protected ResourceBundle |
doGetBundle(String basename,
Locale locale)
Obtain the resource bundle for the given basename and Locale.
|
protected ClassLoader |
getBundleClassLoader()
Return the ClassLoader to load resource bundles with.
|
protected MessageFormat |
getMessageFormat(ResourceBundle bundle,
String code,
Locale locale)
Return a MessageFormat for the given bundle and code,
fetching already generated MessageFormats from the cache.
|
protected ResourceBundle |
getResourceBundle(String basename,
Locale locale)
Return a ResourceBundle for the given basename and code,
fetching already generated MessageFormats from the cache.
|
protected String |
getStringOrNull(ResourceBundle bundle,
String key)
Efficiently retrieve the String value for the specified key,
or return
null if not found. |
protected ResourceBundle |
loadBundle(InputStream inputStream)
Load a property-based resource bundle from the given input stream,
picking up the default properties encoding on JDK 9+.
|
protected ResourceBundle |
loadBundle(Reader reader)
Load a property-based resource bundle from the given reader.
|
protected MessageFormat |
resolveCode(String code,
Locale locale)
Resolves the given message code as key in the registered resource bundles,
using a cached MessageFormat instance per message code.
|
protected String |
resolveCodeWithoutArguments(String code,
Locale locale)
Resolves the given message code as key in the registered resource bundles,
returning the value found in the bundle as-is (without MessageFormat parsing).
|
void |
setBeanClassLoader(ClassLoader classLoader)
Callback that supplies the bean
class loader to
a bean instance. |
void |
setBundleClassLoader(ClassLoader classLoader)
Set the ClassLoader to load resource bundles with.
|
String |
toString()
Show the configuration of this MessageSource.
|
addBasenames, getBasenameSet, getCacheMillis, getDefaultEncoding, getDefaultLocale, isFallbackToSystemLocale, setBasename, setBasenames, setCacheMillis, setCacheSeconds, setDefaultEncoding, setDefaultLocale, setFallbackToSystemLocale
getCommonMessages, getDefaultMessage, getDefaultMessage, getMessage, getMessage, getMessage, getMessageFromParent, getMessageInternal, getParentMessageSource, isUseCodeAsDefaultMessage, resolveArguments, setCommonMessages, setParentMessageSource, setUseCodeAsDefaultMessage
createMessageFormat, formatMessage, isAlwaysUseMessageFormat, renderDefaultMessage, setAlwaysUseMessageFormat
public void setBundleClassLoader(ClassLoader classLoader)
Default is the containing BeanFactory's
bean ClassLoader
,
or the default ClassLoader determined by
ClassUtils.getDefaultClassLoader()
if not running within a BeanFactory.
@Nullable protected ClassLoader getBundleClassLoader()
Default is the containing BeanFactory's bean ClassLoader.
public void setBeanClassLoader(ClassLoader classLoader)
BeanClassLoaderAware
class loader
to
a bean instance.
Invoked after the population of normal bean properties but
before an initialization callback such as
InitializingBean's
InitializingBean.afterPropertiesSet()
method or a custom init-method.
setBeanClassLoader
in interface BeanClassLoaderAware
classLoader
- the owning class loaderprotected String resolveCodeWithoutArguments(String code, Locale locale)
resolveCodeWithoutArguments
in class AbstractMessageSource
code
- the code of the message to resolvelocale
- the locale to resolve the code for
(subclasses are encouraged to support internationalization)null
if not foundAbstractMessageSource.resolveCode(java.lang.String, java.util.Locale)
,
MessageFormat
@Nullable protected MessageFormat resolveCode(String code, Locale locale)
resolveCode
in class AbstractMessageSource
code
- the code of the message to resolvelocale
- the locale to resolve the code for
(subclasses are encouraged to support internationalization)null
if not foundAbstractMessageSource.resolveCodeWithoutArguments(String, java.util.Locale)
@Nullable protected ResourceBundle getResourceBundle(String basename, Locale locale)
basename
- the basename of the ResourceBundlelocale
- the Locale to find the ResourceBundle fornull
if none
found for the given basename and Localeprotected ResourceBundle doGetBundle(String basename, Locale locale) throws MissingResourceException
basename
- the basename to look forlocale
- the Locale to look forMissingResourceException
- if no matching bundle could be foundResourceBundle.getBundle(String, Locale, ClassLoader)
,
getBundleClassLoader()
protected ResourceBundle loadBundle(Reader reader) throws IOException
This will be called in case of a "defaultEncoding"
,
including ResourceBundleMessageSource
's default ISO-8859-1 encoding.
Note that this method can only be called with a ResourceBundle.Control
:
When running on the JDK 9+ module path where such control handles are not
supported, any overrides in custom subclasses will effectively get ignored.
The default implementation returns a PropertyResourceBundle
.
reader
- the reader for the target resourceIOException
- in case of I/O failureloadBundle(InputStream)
,
PropertyResourceBundle.PropertyResourceBundle(Reader)
protected ResourceBundle loadBundle(InputStream inputStream) throws IOException
This will only be called with "defaultEncoding"
set to null
, explicitly enforcing the platform default encoding
(which is UTF-8 with a ISO-8859-1 fallback on JDK 9+ but configurable
through the "java.util.PropertyResourceBundle.encoding" system property).
Note that this method can only be called with a ResourceBundle.Control
:
When running on the JDK 9+ module path where such control handles are not
supported, any overrides in custom subclasses will effectively get ignored.
The default implementation returns a PropertyResourceBundle
.
inputStream
- the input stream for the target resourceIOException
- in case of I/O failureloadBundle(Reader)
,
PropertyResourceBundle.PropertyResourceBundle(InputStream)
@Nullable protected MessageFormat getMessageFormat(ResourceBundle bundle, String code, Locale locale) throws MissingResourceException
bundle
- the ResourceBundle to work oncode
- the message code to retrievelocale
- the Locale to use to build the MessageFormatnull
if no message
defined for the given codeMissingResourceException
- if thrown by the ResourceBundle@Nullable protected String getStringOrNull(ResourceBundle bundle, String key)
null
if not found.
As of 4.2, the default implementation checks containsKey
before it attempts to call getString
(which would require
catching MissingResourceException
for key not found).
Can be overridden in subclasses.
bundle
- the ResourceBundle to perform the lookup inkey
- the key to look upnull
if noneResourceBundle.getString(String)
,
ResourceBundle.containsKey(String)