Spring系列.ApplicationContext接口


之前提到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");

			}
		}
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM