spring boot實戰(第二篇)事件監聽
前言
spring boot在啓動過程中增加事件監聽機制,爲用戶功能拓展提供極大的便利。
支持的事件類型四種
ApplicationStartedEvent
ApplicationEnvironmentPreparedEvent
ApplicationPreparedEvent
ApplicationFailedEvent
實現監聽步驟:
1.監聽類實現ApplicationListener
接口
2.將監聽類添加到SpringApplication
實例
ApplicationStartedEvent
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
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<ApplicationEnvironmentPreparedEvent> {
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<PropertySource<?>> 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
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
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中的監聽器。
spring boot中支持的事件類型定在org.springframework.boot.context.event包中,目前支持的事件類型有如下6種:
ApplicationFailedEvent
ApplicationPreparedEvent
ApplicationReadyEvent
ApplicationStartedEvent
SpringApplicationEvent
ApplicationEnvironmentPreparedEvent
監聽器的使用
第一:首先定義一個自己使用的監聽器類並實現ApplicationListener接口。
第二:通過SpringApplication類中的addListeners方法將自定義的監聽器註冊進去。
ApplicationFailedEvent
ApplicationFailedEvent:該事件爲spring boot啓動失敗時的操作
/**
* spring boot 啓動的時候出現異常事件
* @author www.shareniu.com
*
*/
public class ShareniuApplicationFailedEventListener implements ApplicationListener<ApplicationFailedEvent> {
@Override
public void onApplicationEvent(ApplicationFailedEvent event) {
System.out.println("--------------:ShareniuApplicationFailedEventListener");
Throwable exception = event.getException();
System.out.println(exception);
}
}
可以通過ApplicationFailedEvent 獲取Throwable實例對象獲取異常信息並處理。
ApplicationPreparedEvent
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<ApplicationPreparedEvent> {
@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
ApplicationReadyEvent:上下文已經準備ok。
這個時候就可以通過ApplicationReadyEvent獲取ConfigurableApplicationContext,然後通過ConfigurableApplicationContext 獲取bean的信息。
public class ShareniuApplicationReadyEventListener implements ApplicationListener<ApplicationReadyEvent> {
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
System.out.println("--------------------:ShareniuApplicationReadyEventListener");
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
//ShareniuDemo可以根基自身情況進行測試
ShareniuDemo shareniuDemo = applicationContext.getBean(ShareniuDemo.class);
}
}
ApplicationStartedEvent
ApplicationStartedEvent:spring boot 啓動監聽類。
可以在SpringApplication啓動之前做一些手腳,比如修改SpringApplication實例對象中的屬性值
public class ShareniuApplicationStartedEventListener implements ApplicationListener<ApplicationStartedEvent>{
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
SpringApplication springApplication = event.getSpringApplication();
springApplication.setShowBanner(false);
System.out.println("##############################ShareniuApplicationStartedEventListener");
}
}
SpringApplicationEvent
SpringApplicationEvent:獲取SpringApplication
public class ShareniuSpringApplicationEventListener implements ApplicationListener<SpringApplicationEvent> {
@Override
public void onApplicationEvent(SpringApplicationEvent event) {
System.out.println("-----------------------:ShareniuSpringApplicationEventListener");
SpringApplication springApplication = event.getSpringApplication();
System.out.println("###############"+springApplication);
}
}
ApplicationEnvironmentPreparedEvent
ApplicationEnvironmentPreparedEvent:環境事先準備,spring boot中的環境已經準備ok
可以通過ApplicationEnvironmentPreparedEvent獲取到SpringApplication、ConfigurableEnvironment等等信息, 可以通過ConfigurableEnvironment實例對象來修改以及獲取默認的環境信息。
public class ShasreniuApplicationEnvironmentPreparedEventListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>{
@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<PropertySource<?>> 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);
}
}