Spring 启动加载资源到内存

Posted 龟龟熊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 启动加载资源到内存相关的知识,希望对你有一定的参考价值。

前言

       在一些业务场景中,当容器初始化完成之后,需要处理一些操作,比如一些数据的加载、初始化缓存、特定任务的注册等等。我找到了三种方式解决下面的问题。

1、使用PostConstruct注解

  这种解决方法比较适用于: 在对于接口响应时间要求比较短,而接口中又需要频繁调用数据库查询,或者调用外部系统的情况下,为了加快接口的响应速度,在项目启动时,将通过途径获取的结果初始化到静态变量或者放置到各种缓存中。

首先静态代码块不行,静态代码块的执行顺序在Spring注解之前,当执行的时候,调用请求的Service还没有注入进来,执行时会报空指针错误。

在启动时完成一些初始化的操作,而这些初始化的操作,又要依赖于依赖注入的结果,就无法在构造方法中实现了。为此需要使用@PostConstruct在构造方法之后执行,被@PostConstruct注解的方法会依赖完成后被自动调用。

 关于Constructor,Spring注解,@PostConstruct执行顺序:Constructor >Spring注解> @PostConstruct

@Component
public class TestUtils {
    
    @Autowired
    ICommonService commonService;
    
    public static List<Rsp> resourceList = new ArrayList<>(); //初始化的全局静态变量
    private static ICommonService reCommonService;
    
    @PostConstruct
    public void Init() {
        //查询所有的
        Req reqBean = new Req();
        reCommonService=commonService;    
     reqBean.setFindType(PROVINCE_CITY_FIND_TYPE.FIND_TYPE_B.toString());//查询所有 城市 Rsp rsp=reCommonService.getPaAreaCityInfo(reqBean); resourceList.add(rsp); } }

2、使用ApplicationListener

  

       在初始化缓存或者特定任务的注册的场景下,可以使用Spring提供的ApplicationListener来进行操作。

       首先,要实现ApplicationListener接口并实现onApplicationEvent方法。举例(使用SpringBoot)如下:

public class ApplicationEventListener implements ApplicationListener<ApplicationEvent> {
  @Autowired
  private PubSubService pubSubService;

  @Override
  public void onApplicationEvent(ApplicationEvent event) {
    if (event instanceof ContextRefreshedEvent) {
      ApplicationContext applicationContext = ((ContextRefreshedEvent) event).getApplicationContext();
      GlobolParameters.context = applicationContext;
      BaseLogger.info("ContextRefreshed初始化开始...");
      // 设置上下文
    }
    if (event instanceof ApplicationReadyEvent) {
      //启动发布订阅
      pubSubService = GlobolParameters.context.getBean(PubSubService.class);
      // redis subscribe job
      pubSubService.subscribe();
      // redis publish job
      pubSubService.publish();
    }
    if (event instanceof ApplicationFailedEvent) {
      Throwable exception = ((ApplicationFailedEvent) event).getException();
      BaseLogger.error("【ApplicationFailedEvent】Spring IOC init  error ", exception);
    }
  }
}

  然后实例化ApplicationEventListener类,在Spring Boot中通过一个配置类进行实例化:

@Configuration
public class ListenerConfig {
    @Bean
    public ApplicationEventListener applicationEventListener(){
        return new ApplicationEventListener();
    }
}

  通过上述代码,在SpringListener中做到,启动了发布订阅的服务。

3、启动类显式调用

  如果对外调用的服务,需要依赖启动后放置在容器中的上下文的情况,则需要手动在启动类中获取相应的Bean,调用初始化的方法进行初始化。

public class StartIiApplication{
    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(StartIiApplication.class, args);
        BeanUtil.setApplicationContext(applicationContext);    
        //从启动的容器中获取Bean,并调用初始化方法
        TestUtils util=(TestUtils) applicationContext.getBean("testUtils");
        util.Init();
    
    }
}

 


以上是关于Spring 启动加载资源到内存的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码阅读Spring容器启动原理(上)-配置资源加载和注册

spring源码阅读-- 容器启动之加载BeanDefinition

使用 Angular 7 前端启动 Spring-Boot 应用程序时无法加载资源错误(缺少资源)

Spring Boot Jar 包启动时如何加载外部资源

Spring Boot Jar 包启动时如何加载外部资源

从服务器加载文件到内存