Skip to content

Latest commit

 

History

History
155 lines (112 loc) · 4.84 KB

(8)自定义监听器实战.md

File metadata and controls

155 lines (112 loc) · 4.84 KB

自定义监听器实战

实现方式一

  • 实现ApplicationListener接口,ApplicationListener声明感兴趣的事件
@Order(1)
public class FirstListener implements ApplicationListener<ApplicationStartedEvent> {

    private final static Logger logger = LoggerFactory.getLogger(FirstListener.class);

    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        logger.info("设置框架事件监听器【ApplicationListener】成功 : run firstListener");

    }
}
  • 在spring.factories 配置文件中配置FirstListener事件监听器,key值为org.springframework.context.ApplicationListener
# 通过系统事件监听器,设置自定义事件监听器
org.springframework.context.ApplicationListener=\
  com.example.springboot.source.code.analysis.listener.FirstListener

实现方式三

  • 实现ApplicationListener接口,声明感兴趣的事件ApplicationListener
@Order(3)
public class ThirdListener implements ApplicationListener<ApplicationStartedEvent> {

    private final static Logger logger = LoggerFactory.getLogger(ThirdListener.class);

    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        logger.info("设置框架事件监听器【ApplicationListener】成功 : run thirdListener");
    }
}
  • 在application.properties 内配置事件监听器,key值为context.listener.classes
# 通过系统事件监听器,监听事件
context.listener.classes=\
  com.example.springboot.source.code.analysis.listener.ThirdListener,\

application.properties 内配置的 conext.listener.classes 事件监听器执行优先级最高

// context.listener.classes 是通过 DelegatingApplicationListener 委派给 ApplicationListener
public class DelegatingApplicationListener implements ApplicationListener<ApplicationEvent>, Ordered {
    private static final String PROPERTY_NAME = "context.listener.classes";
    // 在委派过程中,DelegatingApplicationListener 会将 order 优先级设置为最高
    private int order = 0;
    private SimpleApplicationEventMulticaster multicaster;

实现方式四

  • 实现SmartApplicationListener接口
@Order(4)
public class FourthListener implements SmartApplicationListener {

    private final static Logger logger = LoggerFactory.getLogger(FourthListener.class);

    // 通过重写 supportEventType()方法 判断该监听器对哪些事件感兴趣
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return ApplicationStartedEvent.class.isAssignableFrom(eventType)
                || ApplicationPreparedEvent.class.isAssignableFrom(eventType);
    }

    // 编写事件触发逻辑
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        logger.info("设置框架事件监听器【SmartApplicationListener】成功 : run fourthListener");
    }
}
  • 可以通过spring.factories 或 application.properties 或 new SpringApplication().addListeners() 三种方式注入该事件

通过 ContextRefershedEvent 获取 Spirng 上下文

  • 实现ApplicationListener接口,关注ContextRefershedEvent事件
@Component
@Order(1)
public class ApplicationContextContainer implements ApplicationListener<ContextRefreshedEvent> {

    private ApplicationContext applicationContext;

    private static ApplicationContextContainer applicationContextContainer;

    // 当容器上下文刷新完成后,会触发此方法
    @Override
    public void onApplicationEvent(@Nullable ContextRefreshedEvent event) {
      	// 双重检测锁,获取当前容器上下文
        if (event != null && applicationContext == null) {
            synchronized (ApplicationContextContainer.class) {
                if (applicationContext == null) {
                    applicationContext = event.getApplicationContext();
                }
            }
        }
        applicationContextContainer = this;
    }

    // 返回当前自定义容器类的实例
    public static ApplicationContextContainer getInstance() {
        return applicationContextContainer;
    }

    // 从 Spring 容器中获取 Bean
    public <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}
  • 测试,通过普通方法获取Spring容器中的Bean
@SpringBootTest(classes = SpringbootSourceCodeAnalysisApplication.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringbootSourceCodeAnalysisApplicationTests {

    // 测试ContextRefreshEvent事件
    @Test
    public void testContextRefreshEvent() {
        WeatherRunListener weatherRunListener = ApplicationContextContainer.getInstance().getBean(WeatherRunListener.class);
        weatherRunListener.snow();
        weatherRunListener.rain();
    }