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));
}
複製代碼
資源文件以下:框架
經過_en_CN這種格式的命名,可使得MessageSource經過Locale來解析獲取到對應的語言的資源文件。最終能夠根據傳入的語言信息來返回對應的消息。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。