org.springframework.context包增长了ApplicationContext接口,它继承了BeanFactory接口,除了以面向应用框架的风格扩展接口来提供一些额外的功能。不少人以彻底声明的方式使用ApplicationContext,甚至没有以编程的方式去建立它,而是依赖诸如ContextLoader等支持类来自动的实例化ApplicationContext,做为Java EE web应用程序正常启动的一部分。 为了加强BeanFactory在面向框架风格的功能,上下文的包还提供了如下的功能:java
国际化在于对特定地区的访问提供属于特定地区的语言反馈。web
ApplicationContext接口继承了一个叫作MessageSource的接口,所以它也提供了国际化(i18n)的功能。Spring也提供了HierarchicalMessageSource接口,它能够分层去解析信息。spring
Spring提供了ResourceBundleMessageSource和StaticMessageSource两个MessageSource实现。它们两个都实现了HierarchicalMessageSource以便处理嵌套消息。StaticMessageSource不多使用,可是它提供了经过编程的方式增长消息源。编程
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>message.format</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
<bean id="messageUtils" class="com.example.springdemo.utils.MessageUtils">
<property name="messageSource" ref="messageSource"/>
</bean>
复制代码
public class MessageUtils {
private MessageSource messageSource;
public MessageSource getMessageSource() {
return messageSource;
}
public void setMessageSource(MessageSource messageSource) {
this.messageSource = messageSource;
}
public String getMessage(String temp, Object[] message, Locale locale) {
return messageSource.getMessage(temp, message, "Required", locale);
}
}
复制代码
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/spring/message.xml");
String temp = "argument.required";
Object[] objects = new Object[] {
"Java Coder!"
};
MessageUtils messageUtils = context.getBean(MessageUtils.class);
System.out.println(messageUtils.getMessage(temp, objects, Locale.SIMPLIFIED_CHINESE));
}
复制代码
资源文件以下:框架
ApplicationEvent类和ApplicationListener接口提供了ApplicationContext中的事件处理。ide
若是一个bean实现了ApplicationListener接口,而后它被部署到上下问中,那么每次ApplicationEvent发布到ApplicationContext中时,bean都会收到通知。本质上,这是观察者模型。测试
咱们能够自定义本身的事件:ui
public class BlackListEvent extends ApplicationEvent {
private String address;
private String test;
public BlackListEvent(Object source, String address, String test) {
super(source);
this.address = address;
this.test = test;
}
@Override
public String toString() {
return "{address:" + address +",text:" + test + "}";
}
}
复制代码
为了发布一个自定义的ApplicationEvent,在ApplicationEventPublisher中调用publishEvent()方法。一般在实现了ApplicationEventPublisherAware接口并把它注册为一个Spring bean的时候它就完成了。下面的例子展现了这么一个类:this
public class EmailService implements ApplicationEventPublisherAware {
//黑名单
private List<String> blackLists;
private ApplicationEventPublisher publisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void setBlackLists(List<String> blackLists) {
this.blackLists = blackLists;
}
public void sendEmail(String address, String text) {
if (blackLists.contains(address)) {
BlackListEvent event = new BlackListEvent(this, address, text);
publisher.publishEvent(event);
return;
}
//send email
}
}
复制代码
在配置时,Spring容器将检测到EmailService实现了ApplicationEventPublisherAware,并将自动调用setApplicationEventPublisher()方法。实际上,传入的参数将是Spring容器自己;您只需经过ApplicationEventPublisher接口与应用程序上下文进行交互。spa
在实际状况中能够直接使用@Service和@Autowired注解从Ioc容器中获取到容器对象,而不须要实现ApplicationEventPublisherAware类。
这两种我比较倾向于对ApplicationEventPublisherAware的实现,由于事件一般用于处理通用的业务,好比消息推送或者邮件发送,这种功能和系统的主要功能没多大关系,所以能够将他们当成组件放置在别的packet下,下降耦合。
对事件的监听有两种实现方式:
其中2方法更加快捷方便,是spring4.2所引入的新功能。相比起1。2方法能够将复数的监听事件统一放置在一个类下面,方便管理。
public class BlackListNotifier implements ApplicationListener<BlackListEvent> {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
@Override
public void onApplicationEvent(BlackListEvent blackListEvent) {
System.out.println("黑名单:" + blackListEvent);
System.out.println("通知目标用户:" + notificationAddress);
}
}
复制代码
public class BlackListNotifier {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
@EventListener
public void onApplicationEvent(BlackListEvent blackListEvent) {
System.out.println("黑名单:" + blackListEvent);
System.out.println("通知目标用户:" + notificationAddress);
}
}
复制代码
这两种方法均可以实现监听,可是我在测试的时候发现一个问题:
当我采用xml实例化bean的时候:
<beans>
<bean id="blackListNotifier" class="com.example.springdemo.listener.BlackListNotifier">
<property name="notificationAddress" value="blacklist@example.org" />
</bean>
<bean id="emailService" class="com.example.springdemo.service.impl.EmailService">
<property name="blackLists">
<list>
<value>known.spammer@example.org</value>
<value>known.hacker@example.org</value>
<value>john.doe@example.org</value>
</list>
</property>
</bean>
</beans>
复制代码
方法2没法获取到监听事件。
当我将它修改为Java类配置后就能够了:
@Configuration
public class EventConf {
@Bean
public BlackListNotifier blackListNotifier() {
BlackListNotifier blackListNotifier = new BlackListNotifier();
blackListNotifier.setNotificationAddress("unkonw@163.com");
return blackListNotifier;
}
}
复制代码
这里文档上也没有提,但愿有知道的大佬可以为我解答,感谢。
能够将Spring ApplicationContext部署为RAR文件,将上下文和全部他所需的bean的类和JAR库封装在Java EE RAR部署单元中。这至关于独立启动一个ApplicationContext,它在Java EE环境中能够访问Java EE服务资源。RAR部署在一些没用头信息的war文件中更天然的选择,实际上,一个war文件在没有http入口的时候,那么它就仅仅是用来在Java EE环境中启动Spring ApplicationContext。
RAR部署在一些没用头信息的war文件中更天然的选择,实际上,一个war文件在没有http入口的时候,那么它就仅仅是用来在Java EE环境中启动Spring ApplicationContext。