前言
在项目中我们经常会遇到在项目的各个阶段进行一些操作,此时可以使用 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的多种方式。。。