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事件机制的过程。

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 blackList;
		private ApplicationEventPublisher publisher;

		public void setBlackList(List 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 {
		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");

			}
		}
    }

你可能感兴趣的:(Spring系列.ApplicationContext接口)