• 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");
    
    			}
    		}
        }
    
  • 相关阅读:
    java数据库连接池proxool介绍及mysql8小时断开连接问题的说明
    golang 做了个mutex与atomic性能测试
    Pcre 安装
    go err
    go if switch range
    Nginx 处理Http请求头部流程
    go 指针
    golang struct、interface详解
    go slice详解
    Linux基础
  • 原文地址:https://www.cnblogs.com/54chensongxia/p/13094263.html
Copyright © 2020-2023  润新知