SpringBoot使用SpringContextUtils.getBean启动报空指针处理记录

目录

一、现象

二、解决

三、@DependsOn详解

一、现象

        最近需要在一个比较老的系统中添加OSS进行文件上传下载处理,而原有系统中已有处理文件上传和下载处理的相关抽象类和接口,为了不影响原有代码逻辑,只能通过新增实现类的模式进行处理。原有处理逻辑中具体处理实现是通过Spring的Configuration中初始化Bean的方式进行处理(通过application的配置来决定初始化Bean),原有的处理为共享磁盘和SFTP两种方式,两种方式都没有实现的Bean里面调用Spring管理的其他Bean模式进行处理。但是OSS的处理逻辑为了兼容项目中多种模式,通过OssTemplate进行处理,并且在外部封装了对外的API,用以实现系统原有逻辑不变更和简化处理逻辑,封装的服务里面很多Bean都是Spring托管的,为了能够使用这个封装的服务,需要基于原有接口的实现类也用spring托管的Bean,故在初始化中使用了SpringContextUtils类的getBean(Class)方法获取,在WEB应用中正常启动,但是在批处理的应用中报空指针异常,沙雕了。

二、解决

        此处由于需要用Spring管理的bean,故通过查看Spring的Bean加载顺序,发现通过包的远近来进行加载,针对提供的基础服务,SpringContextUtils是否在Configuration的Bean初始化之前初始化是未知的。此时想到了很久之前有个大神处理生产问题时用到的@DependsOn注解(注解含义就是组件A要依赖于另一个组件B,也就是说被依赖的组件B会比组件A先注册到Spring容器中),如果Configuration的@Bean上面增加这个@DependsOn("springContextUtils")是否也跟正常@Component上增加注解一样,先把SpringContextUtils注册到Spring容器里面?

    @Bean
	@DependsOn({"springContextUtils"})
	public FileUploadTemplate getFileSystemMethod() {

再次启动批处理后,一切OK,不会再有空指针异常发生,并且能够正常使用了。

PS:SpringContextUtils源码如下:

@Component
public final class SpringContextUtils implements ApplicationContextAware {

    /**
     * Spring应用上下文环境
     */
    private static ApplicationContext applicationContext;

    /**
     * 获取对象
     *
     * @return Object 一个以所给名字注册的bean的实例
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        return (T) applicationContext.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     */
    public static <T> T getBean(Class<T> clz) {
        return applicationContext.getBean(clz);
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @return boolean
     */
    public static boolean containsBean(String name) {
        return applicationContext.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @return boolean
     */
    public static boolean isSingleton(String name) {
        return applicationContext.isSingleton(name);
    }

    /**
     * @return Class 注册对象的类型
     */
    public static Class<?> getType(String name) {
        return applicationContext.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     */
    public static String[] getAliases(String name) {
        return applicationContext.getAliases(name);
    }

    @Override
    public synchronized void setApplicationContext(ApplicationContext applicationContext) {
        if (SpringContextUtils.applicationContext == null) {
            SpringContextUtils.applicationContext = applicationContext;
        }
    }
}

三、@DependsOn详解

@DependsOn注解是Spring框架中的一个功能,用于定义bean之间的依赖关系。它主要用于控制bean的初始化顺序,确保某些bean在其他bean之前被创建和初始化。@DependsOn注解常用于解决循环依赖、确保某些bean在其他bean之前被创建等场景。

具体作用:

  • 控制bean的初始化顺序:通过@DependsOn可以确保某个bean在另一个bean之前被初始化,从而避免因初始化顺序不当而导致的问题。
  • 解决循环依赖:当两个或多个bean之间存在循环依赖时,可以使用@DependsOn注解来指定bean的初始化顺序,从而解决循环依赖问题。

使用方法: @DependsOn注解可以与@Bean、@Component、@Service等注解一起使用。以下是@DependsOn的一些使用示例:

在Java配置类中,结合@Bean注解使用:

@Configuration
public class AppConfig {

    @Bean
    @DependsOn("beanB")
    public BeanA beanA() {
        return new BeanA();
    }

    @Bean
    public BeanB beanB() {
        return new BeanB();
    }
}

在上面的示例中,beanA依赖于beanB,所以我们使用@DependsOn("beanB")注解来确保beanB在beanA之前被创建和初始化。

在组件类中,结合@Component、@Service等注解使用:

@Service
@DependsOn("beanB")
public class BeanA {
    // ...
}

@Service
public class BeanB {
    // ...
}

在上面的示例中,我们将@DependsOn注解应用于BeanA类上,以确保BeanB在BeanA之前被创建和初始化。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值