Spring 監聽器 ApplicationListener 的使用


前言

在項目中我們經常會遇到在項目的各個階段進行一些操作,此時可以使用 ApplicationListener 接口搭配 ApplicationEvent 類使用 。

ApplicationListener 支持的事件類型

 

  1. ApplicationFailedEvent:該事件為spring boot啟動失敗時的操作

  2. ApplicationPreparedEvent:上下文context准備時觸發

  3. ApplicationReadyEvent:上下文已經准備完畢的時候觸發

  4. ApplicationStartedEvent:spring boot 啟動監聽類

  5. SpringApplicationEvent:獲取SpringApplication

  6. 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的多種方式。。。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM