JAVA一个项目如何预先加载数据?

Posted 盖丽男

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA一个项目如何预先加载数据?相关的知识,希望对你有一定的参考价值。

这里写目录标题

需求

一般我们可能会有一些在应用启动时加载资源的需求,局部或者全局使用,让我们来看看都有哪些方式实现。

实现

@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

  1. 这是一个接口,用户可以自定义实现该接口,具体实现run方法
  2. 任何在上下文容器之内的bean都可以实现run方法
  3. 如果在上下文中,存在多个该接口实现类,可以通过@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事件

以上是关于JAVA一个项目如何预先加载数据?的主要内容,如果未能解决你的问题,请参考以下文章

Java类加载机制

Java类加载机制

Java类加载机制

Spring源码分析Bean加载流程概览

Spring源码分析Bean加载流程概览

没有加载jawt导致java.lang.UnsatisfiedLinkError