前言
在項目中我們經常會遇到在項目的各個階段進行一些操作,此時可以使用 ApplicationListener 接口搭配 ApplicationEvent 類使用 。
ApplicationListener 支持的事件類型
-
ApplicationFailedEvent:該事件為spring boot啟動失敗時的操作
-
ApplicationPreparedEvent:上下文context准備時觸發
-
ApplicationReadyEvent:上下文已經准備完畢的時候觸發
-
ApplicationStartedEvent:spring boot 啟動監聽類
-
SpringApplicationEvent:獲取SpringApplication
-
ApplicationEnvironmentPreparedEvent:環境事先准備
ApplicationEvent
首先繼承結構如下
EventObject
--ApplicationEvent
--SpringApplicationEvent
--ApplicationEnvironmentPreparedEvent
近期在工作中需要通過不同的運行環境(dev、prod)加載不同的配置文件,故本次只針對ApplicationEnvironmentPreparedEvent做不同環境下配置文件加載為例。
1、編寫自己的Listener實現 ApplicationListener 接口,監聽事件使用ApplicationEnvironmentPreparedEvent,實現onApplicationEvent,以下示例可實現加載不同環境下的多個文件。
public class PropertiesListenerConfig implements ApplicationListener<ApplicationEnvironmentPreparedEvent> { private static final Logger logger = LoggerFactory.getLogger(PropertiesListenerConfig.class); private static final ArrayList<String> propertyFileNames = new ArrayList<>(); private static String env = "dev"; public PropertiesListenerConfig(String[] propertyFileName) { propertyFileNames.addAll(Arrays.asList(propertyFileName)); } @Override public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent) { // 讀取配置環境 if (StringUtils.hasText(applicationEnvironmentPreparedEvent.getEnvironment().getActiveProfiles()[0])) { env = applicationEnvironmentPreparedEvent.getEnvironment().getActiveProfiles()[0]; } // 加載配置文件 if (propertyFileNames.size() > 0) { for (String propertyFileName : propertyFileNames) { // 配置需要載入的配置文件 PropertiesListenerConfig.loadAllProperties(propertyFileName); } } } public static Map<String, String> propertiesMap = null; private static void processProperties(Properties props) throws BeansException { if (propertiesMap == null) { propertiesMap = new HashMap<>(); } for (Object key : props.keySet()) { String keyStr = key.toString(); try { // PropertiesLoaderUtils的默認編碼是ISO-8859-1,在這里轉碼一下 propertiesMap.put(keyStr, new String(props.getProperty(keyStr).getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8)); } catch (Exception e) { e.printStackTrace(); } } } public static void loadAllProperties(String propertyFileName) { try { Properties properties = PropertiesLoaderUtils.loadAllProperties(getEnvPropPath(propertyFileName)); processProperties(properties); } catch (IOException e) { e.printStackTrace(); } } /** * 根據配置文件名,獲取系統環境下的配置文件 * * @param propertyFileName 配置文件名稱 * @return 系統環境下的配置文件 */ public static Properties getEnvPropFile(String propertyFileName) { Properties properties = new Properties(); try { properties.load(PropertyValues.class.getClassLoader().getResourceAsStream(getEnvPropPath(propertyFileName))); } catch (IOException e) { e.printStackTrace(); } return properties; } public static String getProperty(String name) { return propertiesMap.get(name); } public static Map<String, String> getAllProperty() { return propertiesMap; } /** * 根據配置文件名,獲取系統環境下的配置文件路徑 * * @param propertyFileName 配置文件名稱 * @return 系統環境下的配置文件路徑 */ private static String getEnvPropPath(String propertyFileName) { return "config/" + env + "/" + propertyFileName; } }
2、監聽類寫完后,將監聽類在啟動類中加載啟動
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class,org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration.class, org.activiti.spring.boot.SecurityAutoConfiguration.class}) @Import({DynamicDataSourceConfig.class}) @EnableAsync public class CapApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication application = new SpringApplication(CapApplication.class); // 配置文件名稱 String[] config = {"fdfs_client.properties"}; // 根據application.yml配置環境,初始化配置文件 application.addListeners(new PropertiesListenerConfig(config)); application.run(args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(CapApplication.class); } }
3、在使用過程中,即可獲得對應配置文件對象。
Properties pro = PropertiesListenerConfig.getEnvPropFile("fdfs_client.properties")
4、如果不想將配置文件寫入啟動類中,也可以在啟動類中只添加Listeners,在ApplicationListener實現類中去加載配置文件列表,如下:
public static void main(String[] args) { SpringApplication application = new SpringApplication(CapApplication.class); application.addListeners(new PropertiesListenerConfig()); application.run(); }
5、需要在監聽實現類中提供默認構造函數,並在實現的onApplicationEvent方法中獲取配置文件列表。
@Override public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEnvironmentPreparedEvent) { // 讀取配置環境 if (StringUtils.hasText(applicationEnvironmentPreparedEvent.getEnvironment().getActiveProfiles()[0])) { env = applicationEnvironmentPreparedEvent.getEnvironment().getActiveProfiles()[0]; } logger.info("當前運行環境{}",env); propertyFileNames.add("fdfs_client.properties"); // 加載配置文件 if (propertyFileNames.size() > 0) { for (String propertyFileName : propertyFileNames) { // 配置需要載入的配置文件 PropertiesListenerConfig.loadAllProperties(propertyFileName); } }
}
6、除了在啟動類中增加監聽外,也可以在application.yml中配置需要監聽的類,效果相同。
下一節記錄配置ApplicationListener的多種方式。。。