applicationContext.getBean 为null
场景:
使用SpringUtils 添加了统一类的调用。单元测试是正常的。
SpringUtils
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(@Nonnull ApplicationContext applicationContext) throws BeansException {
SpringUtils.applicationContext = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static <T> T getBean(Class<T> clazz) {
return applicationContext.getBean(clazz);
}
}
实例化:
@Configuration
@AutoConfigureOrder(value = Ordered.LOWEST_PRECEDENCE)
public class SpringAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "springUtils")
public SpringUtils springUtils() {
return new SpringUtils();
}
}
问题场景1:
在另外一个项目,引用SpringUtils,报错。applicationContext.getBean 这边为null了,设置调试。setApplicationContext也没有进来。
public void setApplicationContext(@Nonnull ApplicationContext applicationContext) throws BeansException {
SpringUtils.applicationContext = applicationContext;
}
检查了下启动类的@ComponentScan的包路径,也是没有问题的。 那会不会有个相似的实现类呢? idea双击Shift,输入 SpringUtil,真的有一个相似的,名字不一样。
把前人写的那个类删了,把引用的地方进行了修改。再处理就正常了。
问题场景2:
修改前人项目,把公共类做一个抽取,做单元测试的时候
@PostConstruct
public void init() {
SysConfig sysConfig = SpringUtils.getBean(SysconfigService.class).getSysConfig("CUST_SYNC_KEY_CONFIG");
if (sysConfig != null && sysConfig.getSysVarValue() != null) {
}
}
这个也是报applicationContext.getBean为null。这边就更容易发现,因为@PostConstrut先初始化了,SpringUtils类都没有实例化。 这边就不适合使用SpringUtils了,把引用类,改@Resource注解进行引入。
项目使用一个统一的路口访问,这样要进行使用@ConditionalOnProperty不同类实现就比较方便,比如是postgre数据库的,sql语法不一样的,就可以直接进行配置,读取不同类。
@Service
public class IassAppConfiguration {
public static IassService createService() {
return SpringUtils.getBean(IassServiceImpl.class);
}
}
总结:
使用applicationContext进行初始化的话,要注意项目里面是有已经存在该实现类,其次注意初始化顺序,不能在项目初始的时候就进行调用。