之前提到Spring中IOC容器的體現其實就是BeanFactory和ApplicationContext的實作,為增強BeanFactory功能,ApplicationContext介面提供了些其他的功能:
- 通過MessageSource介面以i18n方式訪問訊息;
- 通過ResourceLoader介面訪問資源,比如URLs和檔案;
- 實作ApplicationListener介面 事件發布給bean,通過ApplicationEventPublisher介面;
- 加載多個(分層的)背景關系,通過HierarchicalBeanFactory介面,允許每個專注一個特殊層,比如應用程式的web層,
下面來介紹下這些功能,
MessageSource
MessageSource介面主要用于國際化,
事件機制
在某些關鍵點,Spring容器會發布一些ApplicationEvent事件,注冊在容器中的ApplicationListener能監聽到這些事件,這種是典型的觀察者模式, Spring提供了一系列標準事件:
- ContextRefreshedEvent:呼叫refresh()之后;
- ContextStartedEvent:呼叫start()方法;
- ContextStoppedEvent:呼叫context的stop()方法;
- ContextClosedEvent:呼叫context的close()方法后促發;
下面展示下使用Spring事件機制的程序(Spring的事件機制可以實作類似EventBus的功能),
step1:定義事件
public class BlackListEvent extends ApplicationEvent {
private final String address;
private final String test;
public BlackListEvent(Object source, String address, String test) {
super(source);
this.address = address;
this.test = test;
}
// accessor and other methods...
}
step2:發布事件
事件發布通常的做法是定義一個Bean,讓這個Bean實作ApplicationEventPublisherAware介面,讓這個Bean準們負責事件發布作業,
public class EmailService implements ApplicationEventPublisherAware {
private List<String> blackList;
private ApplicationEventPublisher publisher;
public void setBlackList(List<String> blackList) {
this.blackList = blackList;
}
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
public void sendEmail(String address, String text) {
//這邊用來發布事件
if (blackList.contains(address)) {
BlackListEvent event = new BlackListEvent(this, address, text);
publisher.publishEvent(event);
return;
}
// send email...
}
}
step3:接收事件
public class BlackListNotifier implements ApplicationListener<BlackListEvent> {
private String notificationAddress;
public void setNotificationAddress(String notificationAddress) {
this.notificationAddress = notificationAddress;
}
public void onApplicationEvent(BlackListEvent event) {
// notify appropriate parties via notificationAddress...
}
}
事件發布器的publishEvent()方法默認是一個同步方法,所以這個方法會一直阻塞直到所有注冊到容器中的ApplicationListenner執行完畢(當然可以配置執行緒池,實作異步模式),
基于注解的ApplicationListener
注意,分發器還是要自己實作,
@Component
public class BlackListNotifierAnnotaion {
//Order的值越小,越先被呼叫
//基于注解@EventListener的Listenner永遠先與傳統的實作ApplicationListener介面的Listenner被呼叫,
@Order(Integer.MIN_VALUE+1)
@EventListener(classes = {BlackListEvent.class,ContextRefreshedEvent.class})
public void processEvent(ApplicationEvent event){
if(event instanceof BlackListEvent){
System.out.println("收到BlackListEvent1");
}
if(event instanceof ContextRefreshedEvent){
System.out.println("收到ContextRefreshedEvent1");
}
}
@Order(Integer.MIN_VALUE+2)
@EventListener(classes = {BlackListEvent.class,ContextRefreshedEvent.class})
public void processEvent2(ApplicationEvent event){
if(event instanceof BlackListEvent){
System.out.println("收到BlackListEvent2");
}
if(event instanceof ContextRefreshedEvent){
System.out.println("收到ContextRefreshedEvent2");
}
}
}
異步ApplicationListener
@Component
public class BlackListNotifierAnnotaion {
//Order的值越小,越先被呼叫
//基于注解@EventListener的Listenner永遠先與傳統的實作ApplicationListener介面的Listenner被呼叫,
@Order(Integer.MIN_VALUE+1)
@Async("執行緒池name")
@EventListener(classes = {BlackListEvent.class,ContextRefreshedEvent.class})
public void processEvent(ApplicationEvent event){
if(event instanceof BlackListEvent){
System.out.println("收到BlackListEvent1");
}
if(event instanceof ContextRefreshedEvent){
System.out.println("收到ContextRefreshedEvent1");
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/165596.html
標籤:Java
上一篇:2020年java就業前景
