ApplicationListener是SpringBoot的监听器,下面是一个demo
public class ApplicationListenerEnvironmentPrepared implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
System.out.println(getClass().getSimpleName());
}
}
上面用到的事件是ApplicationEnvironmentPreparedEvent,插一句:SpringBoot为ApplicationContextEvent提供了四种事件:
- ApplicationStartedEvent :spring boot启动开始时执行的事件
- ApplicationEnvironmentPreparedEvent:spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
- ApplicationPreparedEvent:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
- ApplicationFailedEvent:spring boot启动异常时执行事件
但是,ApplicationListener的功能不止是止步于此,你可以自定义需要拦截的Event,比如我用到了一个监听事件。
定义好了ApplicationListener下面就是使用了。下面是三种使用的方案
方案一:在启动类中配置
@SpringBootApplication
public class Application {
public static void main(String args[]) {
SpringApplication app = new SpringApplication(applicationClass);
app.addListeners(new StompConnectEvent()); //加入监听事件
app.setBannerMode(Banner.Mode.CONSOLE);
app.run(args);
}
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<Application> applicationClass = Application.class;
}
方案二:在application.properties中配置(多个用逗号隔开)
context.listener.classes=com.StompConnectEvent
上述两种方案有一个共同点,是什么呢?我们来看下。我在StompConnectEvent中加了一个构造方法,看它会在什么时候被启动
我们看到,它会在项目最开始的时候启动(在banner前我一开始楞是没找到),这样在最前面启动,会有什么副作用呢?你试试看在你的Event中使用@Autowired注入一个bean。为什么要注入?总有业务场景需要你在监听事件后做一些事情。注入后你会发现报错 java.lang.NullPointerException: null
加上前面的启动时间和和这个错误的类型,我们不难发现,是因为在启动这个监听器的时候,相应的BeanFactory还没加载。换句话说,启动的太早了!
方案三:@Configuration
说了这么多,其实就是否决了上面两种启动方案(也不能说否决,只能说使用上面两种方案,有一些需求达不到),我的解决方案就是,在定义好ApplicationListener之后,在类前面加上@Configuration,如果不知道@Configuration是啥的自行百度哈~
@Configuration
public class StompConnectEvent implements ……
然后我们再来看下它什么时候会被启动
我们发现启动时间变迟了,然后,惊喜的发现@Autowired注入不报错了所有事务顺利解决~
其实就是对于启动ApplicationListener的方式做了一些说明,在爬坑的时候,没有发现网上有类似的启动说明,如果有更好的方式欢迎指正