2022-6月更文挑战5-一次项目启动阶段无法获取bean的问题

77 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

一次项目启动阶段无法获取bean的问题

前文

首先进行一下问题过程的描述。项目采用springboot搭建,利用@postConstruct进行启动阶段预加载。由于在操作过程中需要根据一定的规则进行对象的动态加载,而在动态加载时在某些情况下需要进行redis的相关操作,因此在新增的对象中选择利用spring上下文进行redis相关bean对象的获取。而在获取的过程中,出现了bean对象空指针的问题,也就是加载该代码时,并未实现bean对象的完全初始化。

代码内容及解决方案

根据上述的问题,首先看一下原始的代码。

启动阶段首先进行预加载初始化的设置:

@PostConstruct
public void init(){
    logger.info("程序启动进行规则链加载");
    chainService.initChain();
}

而在具体的执行方法中,则进行相关对象的动态初始化,主要采用反射实现:

o = (ChainHandler)cons.newInstance(chainDTO.getDetailJsons().get(j),ruleId,nodeId);

而实际我们所创建出来的ChainHandler对象,则需要通过上下文进行bean获取,再进行相应的redis操作:

this.multiTenantRedisUtils = ApplicationContextUtil.getBean(MultiTenantRedisUtils.class);

那么分析一下问题的原因,其实该问题的出现主要就是由于我们是在初始化阶段就需要通过bean上下文进行对象的获取,而也正是依然处于初始化阶段,使得bean对象此时尚未完全创建成功。经过断点分析,可以很轻易的发现此时很多实际需要应用的bean依然为空值。相应的,也就很容易想到解决办法,我们需要在初始化阶段,当进行bean获取前,事先指定该bean需要被创建。那么具体该如何处理,这里采用在初始化阶段所调用的bean对象chainService。我们在chainService中进行redis相关内容的导入,则可以确保当初始化阶段实际的逻辑执行时,需要的bean已经被预先注入到管理器中,也就能够避免获取不到的问题导致的空指针异常。

@Autowired
MultiTenantRedisUtils multiTenantRedisUtils;

后记

  • 千古兴亡多少事?悠悠。不尽长江滚滚流。