需求
一般我们可能会有一些在应用启动时加载资源的需求,局部或者全局使用,让我们来看看都有哪些方式实现。
实现
@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()); } } }