spring boot在启动过程中增加事件监听机制,为用户功能拓展提供极大的便利。
ApplicationStartedEvent
ApplicationEnvironmentPreparedEvent
ApplicationPreparedEvent
ApplicationFailedEvent
1.监听类实现ApplicationListener
接口
2.将监听类添加到SpringApplication
实例
ApplicationStartedEvent
:spring boot启动开始时执行的事件
创建对应的监听类 MyApplicationStartedEventListener.java
package com.lkl.springboot.listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
/**
* spring boot 启动监听类
*
* @author liaokailin
* @version $Id: MyApplicationStartedEventListener.java, v 0.1 2015年9月2日 下午11:06:04 liaokailin Exp $
*/
public class MyApplicationStartedEventListener implements ApplicationListener<ApplicationStartedEvent> {
private Logger logger = LoggerFactory.getLogger(MyApplicationStartedEventListener.class);
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
SpringApplication app = event.getSpringApplication();
app.setShowBanner(false);// 不显示banner信息
logger.info("==MyApplicationStartedEventListener==");
}
}
在该事件中可以获取到SpringApplication
对象,可做一些执行前的设置.
Application.java
类
package com.lkl.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.lkl.springboot.listener.MyApplicationStartedEventListener;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.addListeners(new MyApplicationStartedEventListener());
app.run(args);
}
ApplicationEnvironmentPreparedEvent
:spring boot 对应Enviroment已经准备完毕,但此时上下文context还没有创建。
MyApplicationEnvironmentPreparedEventListener.java
package com.lkl.springboot.listener;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
/**
* spring boot 配置环境事件监听
* @author liaokailin
* @version $Id: MyApplicationEnvironmentPreparedEventListener.java, v 0.1 2015年9月2日 下午11:21:15 liaokailin Exp $
*/
public class MyApplicationEnvironmentPreparedEventListener implements
ApplicationListener {
private Logger logger = LoggerFactory.getLogger(MyApplicationEnvironmentPreparedEventListener.class);
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment envi = event.getEnvironment();
MutablePropertySources mps = envi.getPropertySources();
if (mps != null) {
Iterator> iter = mps.iterator();
while (iter.hasNext()) {
PropertySource> ps = iter.next();
logger
.info("ps.getName:{};ps.getSource:{};ps.getClass:{}", ps.getName(), ps.getSource(), ps.getClass());
}
}
}
}
在该监听中获取到ConfigurableEnvironment
后可以对配置信息做操作,例如:修改默认的配置信息,增加额外的配置信息等等~~~
ApplicationPreparedEvent
:spring boot上下文context创建完成,但此时spring中的bean是没有完全加载完成的。
MyApplicationPreparedEventListener.java
package com.lkl.springboot.listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
/**
* 上下文创建完成后执行的事件监听器
*
* @author liaokailin
* @version $Id: MyApplicationPreparedEventListener.java, v 0.1 2015年9月2日 下午11:29:38 liaokailin Exp $
*/
public class MyApplicationPreparedEventListener implements ApplicationListener<ApplicationPreparedEvent> {
private Logger logger = LoggerFactory.getLogger(MyApplicationPreparedEventListener.class);
@Override
public void onApplicationEvent(ApplicationPreparedEvent event) {
ConfigurableApplicationContext cac = event.getApplicationContext();
passContextInfo(cac);
}
/**
* 传递上下文
* @param cac
*/
private void passContextInfo(ApplicationContext cac) {
//dosomething()
}
}
在获取完上下文后,可以将上下文传递出去做一些额外的操作。
在该监听器中是无法获取自定义bean并进行操作的。
ApplicationFailedEvent
:spring boot启动异常时执行事件 MyApplicationFailedEventListener.java
package com.lkl.springboot.listener;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.context.ApplicationListener;
public class MyApplicationFailedEventListener implements ApplicationListener<ApplicationFailedEvent> {
@Override
public void onApplicationEvent(ApplicationFailedEvent event) {
Throwable throwable = event.getException();
handleThrowable(throwable);
}
/*处理异常*/
private void handleThrowable(Throwable throwable) {
}
}
在异常发生时,最好是添加虚拟机对应的钩子进行资源的回收与释放,能友善的处理异常信息。
在spring boot中已经为大家考虑了这一点,默认情况开启了对应的功能:
public void registerShutdownHook() {
if (this.shutdownHook == null) {
// No shutdown hook registered yet.
this.shutdownHook = new Thread() {
@Override
public void run() {
doClose();
}
};
Runtime.getRuntime().addShutdownHook(this.shutdownHook);
}
}
在doClose()
方法中进行资源的回收与释放。
spring boot提供的四种监听事件到这里就结束了,针对实际业务可添加自定义的监听器,下一节当中将会对spring boot中的监听源码进行分析,理解为什么是这样的。
摘要:spring boot提供了一系列的监听器,方便我们开发人员使用和扩展。
本文咱们详细讲解一下spring boot中的监听器。
spring boot中支持的事件类型定在org.springframework.boot.context.event包中,目前支持的事件类型有如下6种:
ApplicationFailedEvent
ApplicationPreparedEvent
ApplicationReadyEvent
ApplicationStartedEvent
SpringApplicationEvent
ApplicationEnvironmentPreparedEvent
第一:首先定义一个自己使用的监听器类并实现ApplicationListener接口。
第二:通过SpringApplication类中的addListeners方法将自定义的监听器注册进去。
ApplicationFailedEvent:该事件为spring boot启动失败时的操作
/**
* spring boot 启动的时候出现异常事件
* @author www.shareniu.com
*
*/
public class ShareniuApplicationFailedEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationFailedEvent event) {
System.out.println("--------------:ShareniuApplicationFailedEventListener");
Throwable exception = event.getException();
System.out.println(exception);
}
}
可以通过ApplicationFailedEvent 获取Throwable实例对象获取异常信息并处理。
ApplicationPreparedEvent:上下文准备事件。
上下文context已经准备完毕 ,可以通过ApplicationPreparedEvent获取到ConfigurableApplicationContext实例对象。ConfigurableApplicationContext类继承ApplicationContext类,但需要注意这个时候spring容器中的bean还没有被完全的加载,因此如果通过ConfigurableApplicationContext获取bean会报错的。比如报错:
Exception in thread "main" java.lang.IllegalStateException: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@69b0fd6f has not been refreshed yet
获取到上下文之后,可以将其注入到其他类中,毕竟ConfigurableApplicationContext为引用类型
public class ShareniuApplicationPreparedEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationPreparedEvent event) {
System.out.println("###############"+"ShareniuApplicationPreparedEventListener");
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
//如果执行下面代码则报错
//ShareniuDemo shareniuDemo = applicationContext.getBean(ShareniuDemo.class);
//System.out.println(shareniuDemo);
}
}
ApplicationReadyEvent:上下文已经准备ok。
这个时候就可以通过ApplicationReadyEvent获取ConfigurableApplicationContext,然后通过ConfigurableApplicationContext 获取bean的信息。
public class ShareniuApplicationReadyEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
System.out.println("--------------------:ShareniuApplicationReadyEventListener");
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
//ShareniuDemo可以根基自身情况进行测试
ShareniuDemo shareniuDemo = applicationContext.getBean(ShareniuDemo.class);
}
}
ApplicationStartedEvent:spring boot 启动监听类。
可以在SpringApplication启动之前做一些手脚,比如修改SpringApplication实例对象中的属性值
public class ShareniuApplicationStartedEventListener implements ApplicationListener{
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
SpringApplication springApplication = event.getSpringApplication();
springApplication.setShowBanner(false);
System.out.println("##############################ShareniuApplicationStartedEventListener");
}
}
SpringApplicationEvent:获取SpringApplication
public class ShareniuSpringApplicationEventListener implements ApplicationListener {
@Override
public void onApplicationEvent(SpringApplicationEvent event) {
System.out.println("-----------------------:ShareniuSpringApplicationEventListener");
SpringApplication springApplication = event.getSpringApplication();
System.out.println("###############"+springApplication);
}
}
ApplicationEnvironmentPreparedEvent:环境事先准备,spring boot中的环境已经准备ok
可以通过ApplicationEnvironmentPreparedEvent获取到SpringApplication、ConfigurableEnvironment等等信息, 可以通过ConfigurableEnvironment实例对象来修改以及获取默认的环境信息。
public class ShasreniuApplicationEnvironmentPreparedEventListener implements ApplicationListener{
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
System.out.println("###############"+"ShasreniuApplicationEnvironmentPreparedEventListener");
SpringApplication springApplication = event.getSpringApplication();
ConfigurableEnvironment environment = event.getEnvironment();
long timestamp = event.getTimestamp();
Object source = event.getSource();
System.out.println("########################"+springApplication);
System.out.println("########################"+environment);
System.out.println("########################"+timestamp);
System.out.println("########################"+source);
MutablePropertySources propertySources = environment.getPropertySources();
if (propertySources!=null) {
Iterator> iterator = propertySources.iterator();
while (iterator.hasNext()) {
PropertySource> propertySource = (PropertySource>) iterator.next();
System.out.println("##############:propertySource"+propertySource);
}
}
}
}
@RestController
@SpringBootApplication()
public class Application {
@RequestMapping("/")
String index() {
return "xxxxxxxxxxxxx";
}
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(Application.class);
springApplication.addListeners(new ShareniuApplicationStartedEventListener());
springApplication.addListeners(new ShasreniuApplicationEnvironmentPreparedEventListener());
springApplication.addListeners(new ShareniuApplicationPreparedEventListener());
springApplication.addListeners(new ShareniuApplicationFailedEventListener());
springApplication.addListeners(new ShareniuApplicationReadyEventListener());
springApplication.addListeners(new ShareniuSpringApplicationEventListener());
springApplication.run(args);
}
}