[springBoot]震惊!多线程中使⽤@Autowired居然会发⽣这样的事!
近期,在项⽬中需要⽤到多线程,⽽且需要读取配置⽂件中RocketMq的相关参数,于是乎⾃⾃然⽽然的将配置⽂件映射到实体类中(据说Spring不建议这样⼲?),重复三遍,以后具体查⼀下:
为什么Spring不建议将配置映射到实体类?
为什么Spring不建议将配置映射到实体类?
为什么Spring不建议将配置映射到实体类?
然后,⾃然⽽然的⽤@Autowired在多线程中注⼊这个实体类!就这样奇迹发⽣了…
在多线程中注⼊的实体类⼀直 空指针异常,⽽在test中却完全没问题,说明我的映射是成功了的,那,为啥?
经过⼀番与度娘的激烈讨论,原来如此:
在线程中为了安全,是防注⼊的
那,这岂不是很坑,不过为了安全,我忍了!
复盘⼀下我们的应⽤场景
假设application.properties中是这样的(yml⽂件同理):
user.name=aran
user.sex=male
user.age=18
user.job=coder
通过实体类进⾏配置⽂件映射:
package st.config;
import org.t.properties.ConfigurationProperties;
import t.annotation.Configuration;
import lombok.Data;
@Data
@Configuration
@ConfigurationProperties(prefix ="user")
public class PropConfig {
private String name;
private String sex;
private String age;
private String job;
@Override
public String toString(){
return"PropConfig [name="+ name +", sex="+ sex +", age="+ age +", job="+ job +"]";
}
}
简单写⼀个线程类:
package threads;
import org.springframework.beans.factory.annotation.Autowired;
import st.config.PropConfig;
public class TestThreads implements Runnable{
@Autowired
PropConfig propConfig;
@Override
public void run(){
System.out.println("进⼊线程"+ Thread.currentThread().getName());
System.out.println("==================开始读取参数========================");  System.out.Name());
System.out.Age());
System.out.println("=======================参数读取完毕==================="); }
}
为了⽅便,我就直接在主类中启动⼀个线程:
package st;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import threads.TestThreads;
@SpringBootApplication
public class AutowiredInRunnableApplication {
public static void main(String[] args){
SpringApplication.run(AutowiredInRunnableApplication.class, args);
new Thread(new TestThreads()).start();
}
}
启动,结果如下:
果然,空指针异常,我们在测试类中试⼀下看:
@Autowired
PropConfig propConfig;
@Test
void getConfig(){
System.out.println("进⼊线程"+ Thread.currentThread().getName());
System.out.println("==================开始读取参数========================");  System.out.Name());
System.out.Age());
System.out.println("=======================参数读取完毕==================="); }
spring到底是干啥的
在测试类中,我们 成功拿到了参数,⽽在线程中,确实不可以那怎么解决,据说有这样三种⽅法2:
1. 内部类
定义⼀个含有内部类的类:
package st.byInnerClass;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import st.config.PropConfig;
@Component
public class AnInnerClazz {
@Autowired
PropConfig propConfig;
public void excute(){
new Thread(new Worker()).start();
}
private class Worker implements Runnable{
@Override
public void run(){
System.out.println("我是内部类执⾏的Run⽅法!");
System.out.println("==========开始读取配置参数==========");
System.out.println("name:"+ Name());
System.out.println("age:"+ Age());
System.out.println("==========结束读取配置参数==========");
}
}
}
此时,我们就可以通过在外部类中注⼊AnInnerClazz,便可以在Worker线程中获取配置参数:⽐如,在Controller中:
package st.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import st.byInnerClass.AnInnerClazz;
import st.config.PropConfig;
@RestController
public class TestController {
@Autowired
AnInnerClazz inner;
@GetMapping("/user")
public void getUser(){
}
}
在test中测试⼀下:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。