前言
在项目中我们经常会遇到在项目的各个阶段进行一些操作,此时可以使用 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中配置需要监听的类,效果相同。
![](https://i-blog.csdnimg.cn/blog_migrate/7f5c8a52284404dea35441f2cecdcd9d.png)
下一节记录配置ApplicationListener的多种方式。。。