【SpringBoot】如何在 Utils 工具类中注入 Bean

一、背景

在 controller 层想使用一个静态工具,这个静态工具要使用其它组件。

我们经常要使用 @Autowired 注解注入 Service 或者 Mapper 接口,在 service 层中注入其它的service 接口或者 mapper 接口都是可以的,但是如果我们要在我们自己封装的 Utils 工具类中使用 @Autowired 注解注入 Service 或者 Mapper 接口,直接注入是不可能的,因为 Utils 使用了静态的方法,我们是无法直接使用非静态接口的,当我们遇到这样的问题,我们就要想办法解决了。

二、错误示范:在静态字段上注入

1、Controller

    @PostMapping("/test")
    public String test() {
        WelcomeUtil.welcome();
        return "test utils success!";
    }

2、工具类

@Component
public class WelcomeUtil {

    @Autowired
    private static Hello hello;

    public static void welcome() {
        hello.sayHello();
    }

}

3、引入的组件

@Component
public class Hello {

    public void sayHello() {
        System.out.println("Hello");
    }

}

4、测试接口

localhost:8080/testUtils/test

运行结果:

java.lang.NullPointerException: null
	at com.example.demo.utils.WelcomeUtil.welcome(WelcomeUtil.java:18) ~[classes/:na]
	at com.example.demo.controller.HelloController.test(HelloController.java:21) ~[classes/:na]

总结:在工具类中直接注入,在调用工具类方法时会报空指针异常,需要设置 bean 的注入。 

三、方案二

其余代码与上边相同

1、工具类

@Component
public class WelcomeUtil {

    private static Hello hello;

    public static void welcome() {
        hello.sayHello();
    }

    @Autowired
    public void setHello(Hello hello) {
        WelcomeUtil.hello = hello;
    }

}

2、测试接口

localhost:8080/testUtils/test

运行结果:

"test utils success!"

四、方案三

1、工具类(使用 @PostConstruct 注解)

@Component
public class WelcomeUtil {

    @Autowired
    private Hello hello;

    private static WelcomeUtil welcomeUtil;

    @PostConstruct
    public void init() {
        // 可以加载多个组件
        welcomeUtil = this;
        welcomeUtil.hello = this.hello;
    }

    public static void welcome() {
        welcomeUtil.hello.sayHello();
    }

}
  1. 将 WelcomeUtil 上添加 @Component 声明其为 bean 组件。
  2. 使用 @Autowired 注入启动类
  3. 在 WelcomeUtil 声明一个 静态的私有变量 private static WelcomeUtil welcomeUtil;
  4. 添加共有的 init 方法,并用 @PostConstruct 声明在项目启动的时候进行执行该方法,也可以理解为在 spring 容器初始化的时候执行该方法。

想要深入了解该注解的,可以看我这篇文章:【Java基础】@PostConstruct 和 @PreDestroy 注解的使用

2、测试接口

localhost:8080/testUtils/test

运行结果:

"test utils success!"

五、方案四

1、ApplicationContextHolderUtil 工具类(范例统一写法,基本没有什么变化)

/**
 * 获取 spring 容器,以访问容器中定义的其它 bean
 */
@Component
@Slf4j
public class ApplicationContextHolderUtil implements ApplicationContextAware {
 
    // Spring 应用上下文环境
    private static ApplicationContext applicationContext;
 
    /**
     * 重写接口的方法,该方法的参数为框架自动加载的IOC容器对象
     * 该方法在启动项目的时候会自动执行,前提是该类上有IOC相关注解,例如@Component
     * @param applicationContext ioc容器
     * @throws BeansException e
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 将框架加载的ioc赋值给全局静态ioc
        ApplicationContextHolderUtil.applicationContext = applicationContext;


        log.info("==================ApplicationContext加载成功==================");
    }
 
    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
 
    /**
     * 获取对象
     * @param name
     * @return Object 一个以所给名字注册的 bean 的实例(service 注解方式,自动生成以首字母小写的类名为 bean name)
     */
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }
 
    //通过class获取Bean.
    public static  T getBean(Class clazz){
        return getApplicationContext().getBean(clazz);
    }
 
    //通过name,以及Clazz返回指定的Bean
    public static  T getBean(String name,Class clazz){
        return getApplicationContext().getBean(name, clazz);
    }
}

2、工具类

@Component
public class WelcomeUtil {

    public static void welcome() {
        ApplicationContextHolderUtil.getApplicationContext()
                .getBean(Hello.class).sayHello();
    }

}

3、测试接口

localhost:8080/testUtils/test

运行结果:

"test utils success!"

六、参考文档

Spring boot遇坑之工具类中注入 bean

SpringBoot--将组件注入到静态工具类--方法/实例

你可能感兴趣的:(spring,boot,java,spring)