java疑难杂症:多线程下@Resource和@Autowired和@Value 注入为null的解决办法
方法一:关于@Resource和@Autowired为null的解决办法
新建一个 ApplicationContext(spring上下文对象) 的工具类SpringContextUtil
public class SpringContextUtil {
private static ApplicationContext applicationContext;
// 设置上下文
public static void setApplicationContext(ApplicationContext context) throws BeansException {
applicationContext = context;
}
// 获取上下文
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
// 通过名字获取上下文中的bean
public static Object getBean(String name) {
if(name == null || name.length()==0) {
return null;
}
try {
String beanName = "";
if(name.length() >1){
beanName = name.substring(0, 1).toLowerCase() + name.substring(1);
} else {
beanName = name.toLowerCase();
}
return applicationContext.getBean(beanName);
} catch (Exception ex){
ex.printStackTrace();
return null;
}
}
// 通过类型获取上下文中的bean
public static <T> T getBean(Class<T> clazz) {
try {
return (T) applicationContext.getBean(clazz);
} catch(Exception ex) {
ex.printStackTrace();
return null;
}
}
}
然后在springboot 启动类中注入上下文对象
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(MyApplication.class, args);
SpringContextUtil.setApplicationContext(run);
// 测试
// 自定义方法调用启动线程
syncUserTable();
}
}
/**
* 线程开启方法
**/
private static void syncUserTable() {
// 实例化线程
Thread thread = new SyncUserTable();
// 开启线程
thread.start();
}
线程类中的run() 方法如下:
@Override
public void run() {
// 测试mapper 是否可用
UserMapper userMapper = SpringContextUtil.getBean(UserMapper.class);
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("name", "张三");
Integer integer = userMapper.selectCount(queryWrapper);
System.out.println(integer); // 打印结果:1
}
到此成功获取到用户表中name字段为“张三”的对象数量为1
方法二:多线程下@Value注入失败的解决办法
配合上面在启动类中加入的工具类SpringContextUtil ,从工具类中获取org.springframework.core.env.Environment 对象
Environment env = SpringContextUtil.getBean(Environment.class);
String loginUrl = env.getProperty("api.loginUrl");
System.out.println("loginUrl -->" + loginUrl); // 打印结果: loginUrl -->http://localhost:80
application.yml 如下:
#服务配置
server:
port: 9002
api:
loginUrl: 'http://localhost:80'