@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 的问题就解决了。
网友评论