1 监听器的基本概念
监听器就是监听某个对象的状态发生变化的组件,监听器的相关概念:
- 事件源:被监听的对象
- 监听器:用于监听事件源对象,事件源对象状态的变化都会触发监听器
- 响应行为:监听器监听到事件源的状态变化时的响应
2 SpringBoot中的监听器
- CommandLineRunner:应用程序启动完成后
- ApplicationRunner:应用程序启动完成后
- ApplicationContextInitializer:应用程序初始化之前
- SpringApplicationRunListener:应用程序全阶段监听
上述第四个监听器“应用程序全阶段监听”中的各个阶段如下:
- 应用程序开始启动--starting
- 环境准备完成--environmentPrepared
- spring容器准备完成--environmentPrepared
- spring容器加载完成--environmentPrepared
- 应用程序启动完成--started
- 应用程序开始运行--running
- 应用程序运行时抛出异常时调用--failed
上述4个监听器中,后两个监听器涉及到程序启动之前的监听,而我们这次主要针对程序启动之后的监听器展开学习。所以接下来虽然会介绍上述四个监听器的简单使用,但是只会针对前两个监听器进行实际案例的使用介绍。
监听器1:CommandLineRunner:应用程序启动完成后
/**
* 监听,当前应用程序启动之后,做一些事情
* 把所有的用户数据缓存到redis,而不是每次第一次点击才进行缓存
*/
@Component
public class My01CommandLineRunnerListener implements CommandLineRunner {
/**
* 当应用程序启动后,会执行run方法
* 参数:主函数的参数列表
*/
@Override
public void run(String... args) throws Exception {
System.out.println("当前应用程序已经启动完成,主函数参数:"+args);
}
}
监听器2:ApplicationRunner:应用程序启动完成后
/**
* 监听,当前应用程序启动之后,做一些事情
* 把所有的用户数据缓存到redis,而不是每次第一次点击才进行缓存
*/
@Component
public class My02ApplicationRunListener implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("当前应用程序已经启动完成,主函数参数:"+args);
}
}
监听器3:ApplicationContextInitializer:应用程序初始化之前
/**
* 在spring容器初始化之前执行
*/
public class My03ApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("spring容器开始初始化");
}
}
监听器4:SpringApplicationRunListener:应用程序全阶段监听
/**
* 应用程序启动全流程,监听器
*/
public class My04SpringApplicationRunListener implements SpringApplicationRunListener {
public My04SpringApplicationRunListener(SpringApplication application, String[] args) {}
@Override
public void starting(){
System.out.println("应用程序开始启动:starting");
}
@Override
public void environmentPrepared(ConfigurableEnvironment environment){
System.out.println("应用程序环境准备完成:environmentPrepared");
}
@Override
public void contextPrepared(ConfigurableApplicationContext context){
System.out.println("应用程序的spring容器准备完成:contextPrepared");
}
@Override
public void contextLoaded(ConfigurableApplicationContext context){
System.out.println("应用程序的spring容器装载完成:contextLoaded");
}
@Override
public void started(ConfigurableApplicationContext context){
System.out.println("应用程序的启动完成:started");
}
@Override
public void running(ConfigurableApplicationContext context){
System.out.println("应用程序正常运行:running");
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception){
System.out.println("应用程序运行出错:failed");
}
}
3 监听器简单案例
目标:当应用程序启动完成时,完成redis缓存的初始化。
步骤
- 实现ApplicationRunner接口,重写run()方法
- 注入UserService接口实现类(用来从Mysql中查询数据)及RedisTemplate对象(用来把数据存到redis)
- 将用户数据存入redis缓存
/**
* 初始化项目时,就查询所有用户数据到缓存中
*/
@Component
public class RedisCacheInitializerListener implements ApplicationRunner {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private UserService userService;
@Override
public void run(ApplicationArguments args) throws Exception {
//拿到所有用户数据
List<User> users = userService.findAll();
//数据存入redis
redisTemplate.boundValueOps(UserController.key).set(users);
System.out.println("监听器初始化redis缓存成功");
}
}
@RestController
public class UserController {
@Autowired
private UserService service;
@Autowired
private RedisTemplate redisTemplate;
//缓存的为唯一标识:redis中的key值(全限定类名+方法名称),value是查询所有用户的结果
public static final String key = UserService.class.getName()+".findAll";
/**
* 查询所有用户
* @return
*/
@RequestMapping("/user/findAll")
private List<User> findAll(){
/**
* 首先从redis缓存中取数据:key,service接口的全限定名称+方法名称
* 如果有返回给用户,如果没有从mysql查返回给用户并存到reids
*/
//函数返回值,即用户信息
List<User> users = null;
//从redis取数据
users = (List<User>) redisTemplate.boundValueOps(key).get();
//如果没取到,就是从mysql查数据,并且保存一份到缓存,如果查到了就直接返回
if(users==null){
//缓存没数据,去mysql查,结果还是要存一份到redis(针对监听器,这个步骤其实没必要)
users = service.findAll();
redisTemplate.boundValueOps(key).set(users);
System.out.println("从数据库取数据");
}else {
System.out.println("从redis缓存中取数据");
}
return users;
}
}