美文网首页Java 杂谈JavaSpring-Boot
线程类中使用@Autowired注入Bean

线程类中使用@Autowired注入Bean

作者: hllcve_ | 来源:发表于2019-07-05 23:22 被阅读5次

@Autowired注入Spring Bean,则当前类必须也是Spring Bean才能注入成功,不能用new xxx()来获得对象,这种方式获得的对象也无法使用@Autowired注解注入Bean。

最近做项目时用到了线程,利用多线程来并行执行任务,在线程类中使用 @Autowired 注解注入的Bean,这时就出现了一个的问题,调用相关方法时报 NullPointerException,刚开始认为是注入的有问题,后来发现在其他类中调用时没有问题的,唯独在这个线程类中调用时报错,后来百度一番之后发现,原来在线程中为了线程安全,是防注入的,但是还需要用到这个Bean,所以只能另想办法了。

这时候需要用到Spring的一个接口ApplicationContextAware,当一个类实现了这个接口之后,这个类就可以获得ApplicationContext中的所有bean。
/**
 * ApplicationContextProvider
 *
 * @author shenhelin
 * @date 2019-07-04
 **/
@Component
public class ApplicationContextProvider implements ApplicationContextAware {

    /**
     * 上下文对象实例
     */
    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextProvider.applicationContext = applicationContext;
    }

    /**
     * 获取Spring上下文
     *
     * @return
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通过name获取Bean
     *
     * @param name
     * @return
     */
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    /**
     * 通过class获取Bean
     *
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通过name,以及Clazz返回指定的Bean
     *
     * @param name
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

}

之后就可以在线程类中的构造方法中,通过调用工具类中的 ApplicationContextProvider.getBean() 就可以拿到实例了,在构造方法中我们将需要的bean对象注入,然后就可以正常使用了。

public SendUniformMessageTask(String taskName, List<String> openIdList, Map<String, MpTemplateMsgData> map) {
    this.taskName = taskName;
    this.openIdList = openIdList;
    this.map = map;
    this.restTemplate = ApplicationContextProvider.getBean(RestTemplate.class);
    this.weChatProperties = ApplicationContextProvider.getBean(WeChatProperties.class);
    this.miniProgramProperties = ApplicationContextProvider.getBean(MiniProgramProperties.class);
    this.miniProgramService = ApplicationContextProvider.getBean(IMiniProgramService.class);
}

这样一来,在线程中使用 @Autowired 注解注入的bean,调用方法时报 NullPointerException 的问题就解决了。

相关文章

网友评论

    本文标题:线程类中使用@Autowired注入Bean

    本文链接:https://www.haomeiwen.com/subject/aobyhctx.html