这里写目录标题
- 需求
- 实现
- @Autowired
- @PostConstruct
- 实例
- CommandLineRunner
- 实例
- ApplicationListener
- 实例
- 参考
需求
一般我们可能会有一些在应用启动时加载资源的需求,局部或者全局使用,让我们来看看都有哪些方式实现。
实现
@Autowired
如果是某个类里需求某个父类的所有子类,不论是接口还是抽象类,其实都可以使用@Autowired的批量注入,非常方便。
//此处假设我们的Animal是个接口,有5个不同的实现类,可以使用以下方式批量注入使用。
@Autowired
private List<Animal> animalList;
@Autowired
private Map<String,Animal> animalMap;
@PostConstruct
PostConstruct是java提供的注解,可以在spring 的项目中使用,它会在Autowired注解之后,init方法之前生效。
这个实现跟下面的差不多,举个例子
实例
其他代码参考下面的
@Component
public class InitTask implements CommandLineRunner {
@Resource
private Animal cat;
@Autowired
@Qualifier("dog")
private Animal dog;
@PostConstruct
public void init(){
//这里写实现
//可以在另一个类里定义好静态属性和方法,在这里将内容填充进去
AnimalFactory.produce("cat",cat);
AnimalFactory.produce("dog",dog);
}
}
CommandLineRunner
- 这是一个接口,用户可以自定义实现该接口,具体实现run方法
- 任何在上下文容器之内的bean都可以实现run方法
- 如果在上下文中,存在多个该接口实现类,可以通过@order注解,指定加载顺序
实例
@Component
public class InitTask implements CommandLineRunner {
@Resource
private Animal cat;
@Autowired
@Qualifier("dog")
private Animal dog;
@Override
public void run(String... args) throws Exception {
//这里写实现
//可以在另一个类里定义好静态属性和方法,在这里将内容填充进去
AnimalFactory.produce("cat",cat);
AnimalFactory.produce("dog",dog);
}
}
public class AnimalFactory {
private static Map<String, Animal> animalMap=new HashMap<>();
public static void produce(String name,Animal animal){
animalMap.put(name,animal);
}
public static void lookup(String name){
animalMap.get(name);
}
}
ApplicationListener
ApplicationListener关注的是ApplicationEvent,spring中所有的事件都继承自ApplicationEvent,其中ApplicationContextEvent是主要的容器事件,它有容器启动、刷新、停止以及关闭各种事件的子类。
SpringApplicationEvent是和SpringApplication生命周期有关的所有事件的父类。
所以就本需求来说,我们主要关注ApplicationContextEvent的实现。
Spring提供如下几个内置事件:
》ContextRefreshEvent: ApplicationContext容器初始化或刷新触发该事件。此处的初始化是指,所有Bean 被成功装载,后处理Bean被检测并激发,所有Singleton Bean被预实例化,ApplicationContext容器已就绪可用。
》ContextStartedEvent: 当使用ConfigurableApplicationContext(ApplicationContext的子接口)接口的start()方法启动ApplicationContext容器时触发该事件。容器管理生命周期的Bean实例将获得一个指定的启动信号,这在经常需要停止后重新启动的场合比较常见。
》ContextClosedEvent:当使用ConfigurableApplicationContext接口的close()方法关闭ApplicationContext容器时触发该事件。
》ContextStoppedEvent:当使用ConfigurableApplicationContext接口的stop()方法使ApplicationContext停止时触发该事件。此处的“停止”意味着容器管理生命周期的Bean实例将获得一个指定的停止信号,被停止的Spring容器可在此调用start()方法重新启动。
》RequestHandledEvent:Web相关的事件,只能运用于使用DispatcherServlet的Web运用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。
所以我们可以通过关注ContextRefreshEvent事件来实现需求。
实例
@Component
public class InitListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (Objects.isNull(event)){
return;
}
ApplicationContext applicationContext=event.getApplicationContext();
if (Objects.isNull(applicationContext)||Objects.isNull(applicationContext.getParent())){
return;
}
Map<String, Animal> animalMap= BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext,Animal.class,false,false);
if (Objects.isNull(animalMap)){
throw new RuntimeException("未找到动物");
}
for (Map.Entry<String,Animal> animal:animalMap.entrySet()){
AnimalFactory.produce(animal.getKey(),animal.getValue());
}
}
}
参考
Spring ApplicationContext的事件机制
关于Spring JavaWeb工程中的ContextRefreshedEvent事件