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