Spring使用LoadTimeWeaver当将类加载进JVM时进行动态转换。
为了使得加载时间织入,在你的@Configuration类上加入@EnableLoadTimeWeaving
。
@Configuration
@EnableLoadTimeWeaving
public class AppConfig {
}
或者是使用元素context:load-time-weaver
只要配置了ApplicationContext。ApplicationContext中的任何Bean可能实现LoadTimeWearveAware,从而接受load-time weaver 实例的引用。与Spring 的JPA一起使用是很有用的。这里load-time weaving对于JPA 类转换是很必要的。详情参考LocalContainerEntityManagerFactoryBean
的doc文档。对于更多详情参考Section 9.8.4, “Load-time weaving with AspectJ in the Spring Framework”.
5.15 ApplicaitionConetext的额外功能
如本章所讲,org.springframework.beans.factory包提供了基本函数管理和操作beans,也包含了编程的方式。org.springframework.context包添加了ApplicationContext接口,其继承了BeanFactory接口,也继承了其他的接口从而添加额外的功能。许多使用者一般以申明的方式使用ApplicationContext,而不是程序化编程,但是作为替代依赖支持类比如ContextLoader自动实例化一个ApplicationContext,其作为JavaEE web应用程序启动过程的一部分。
为增强BeanFactory功能,Context包也提供了其他的功能:
ApplicationEventPublisher
接口HierarchicalBeanFactory
接口,允许每个专注一个特殊层,比如应用程序的web层。5.15.1 使用MessageSource国际化
ApplicationContext接口继承了MessageSource接口,并且提供了国际化功能。Spring也提供了HierarchicalMessageSource
接口,这样可以分层的解决消息。这个接口一起提供了这样的功能:Spring可以影响消息的resolution。这些接口包含了如下方法:
String getMessage(String code, Object[] args, String default, Locale loc)
:这个基本方法从MessageSource
接收消息。当没有从指定的locate中找到消息时,就使用默认的消息。传递的参数变成默认的值,标准包提供MessageSource功能String getMessage(String code, Object[] args, Locale loc)
:基本上与前面的方法相同,但是也有区别:没有指定默认的消息;如果没有找到消息,抛出NoSuchMessageException
异常String getMessage(MessageSourceResolvable resolvable, Locale locale)
:前面方法中的参数属性全部封装类MessageSourceResolvable
中。当加载一个ApplicationContext
,其自动查找Context中的MessageSource
bean。这个bean必须有名字messageSource
。如果没有发现找到这样的bean,调用前面的方法委托给消息源(message source)。如果没有找到消息源,ApplicationContext
找其有相同名字messageSource的上一级类。如果找到了,以MessageSource
使用这个bean。如果ApplicationContext没有找到消息来源,实例化一个空的DelegatingMessageSource
获取上述方法的调用。
Spring提供了两个MessageSource的实现,ResourceBundleMessageSource和StaticMessageSource。两者都实现了HierarchicalMessageSource
来嵌入消息。StaticMessageSource仅提供编程的方式将消息添加到源中。下面是ResourceBundleMessageSource
用法的例子:
format
exceptions
windows
# in format.properties
message=Alligators rock!
# in exceptions.properties
argument.required=The {0} argument is required.
执行MessageSource功能的的程序将在下一个例子中演示。记住所有的ApplicationContext实现也是MessageSource实现,所以其类型可以转化为MessageSource接口。
public static void main(String[] args) {
MessageSource resources = new ClassPathXmlApplicationContext("beans.xml");
String message = resources.getMessage("message", null, "Default", null);
System.out.println(message);
}
综上所述,MessageSource被定义为一个beans.xml的文件,存在于系统路径的根目录下。messageSource bean定义通过其beannames属性涉及到大量的资源束。列表中传递的三个文件,其对应着beannames属性位于系统路径的根目录并且分别称作format.property,exception.property和windows.property。
下一个例子显示了传递给消息查找的参数。这些参数将转化为String类型并且插入到查找信息的占位符中。
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);
}
}
调用execute()方法的输出结果如下:
The userDao argument is required.
关于国际化,Spring不同的MessageResource实现遵循相同的locate resolution并且以标准JDK的ResourceBundle遵循规则。简而言之,还是以前面的例子messageResource为例子,如果你想定义en-GB的本地化,你将分别创建format_en_GB.properties
, exceptions_en_GB.properties
,和windows_en_GB.properties
三个文件。
一般地,locate resolution 由应用程序的周遭环境决定。在这个例子中,英语本地化消息将手动指定。
# 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);
}
上述程序打印结果如下:
Ebagum lad, the userDao argument is required, I say, required.
你也可以使用MessageSourceAware
接口获取任何已定义MessageResource的依赖。任何定义在一个ApplicationContext中的任何bean,其已经实现了MessageSourceAware
接口,当创建和配置bean时,将注入到应用程序上下文的MessageResource。
注意:作为可选的ResourceBundleMessageSource
,Spring提供了ReloadableResourceBundleMessageSource
类。这个变体支持相同的束文件格式,但是比基于标准JDK的ResourceBundleMessageSource
实现更加灵活。尤其是,其允许从Spring的任何资源位置读取文件,而不仅仅是类路径,并且支持从束属性文件的热加载(需要高效缓存它们时)。