【springboot】springboot自动(@Autowired)注入方式与自己new实例的区别

在上期讲到springboot搭建的多模块项目(module)Service自动注入(@Autowired)空指针错误解决的时候https://blog.csdn.net/Myuhua/article/details/84317582,跟大家说到要把为什么在new对象跟自动注入对象同时使用时会空指针,还有就算new对象怎么处理才不会出现空指针的问题给大家说一下,今天我就来还账了。

谈到这个问题,根本原因就在当spring框架帮我们管理的时候会帮我们自动的初始化接下来用到的一些属性,而通过用new实例的方法去做,在实例中用到的某些属性可能就需要我们自己去给set值做一个初始化,否则就有可能产生空指针的错误。

(1)首先,我们先看一下正常的情况,把管理权交给spring替我们去管理:

在下面代码的第4行将UploadService 注入后,在第18行去对它当中的uploadBlock()方法做了一个调用(注意:这个时候第10行的代码如果是被注释掉的,上面第4行的注入就会生效,反之失效!),我们在18行做引用的时候,在方法中用到了ReadFilePathProperties这一个类,在程序运行过程中框架就帮我们把它给初始化了,就不会出现空指针的错误,程序正常运行。

public class TestController {
1    @Autowired
2    private FileToByteArrayService fileToByteArrayService;
3    @Autowired
4    private UploadService uploadService;
5    @Test
6    public void testDemo() throws IOException {
7        //原文件的位置(需根据自己情况修改)
8        String fileSrc = "D:\\tempfile\\elasticsearch-6.4.2.zip";
9        byte[] bytes = fileToByteArrayService.fileToBytes(fileSrc);
        /**
         * 演示过程中,下面这行代码是否注释掉说明:
         * 1.演示通过springboot注入方式去调用UploadService()中的方法需要注释掉。
         * 2.演示通过new实例方式进入到UploadService去调用方法出现空指针问题,则需要保留这行代码。
         * 3.演示通过new实例方式进入到UploadService去调用方法,通过在UploadService中set值解决问题,则这行代码不能注释掉。
         */
10        //UploadService uploadService = new UploadService();
        try {
11          UploadBlockInputVo param = new UploadBlockInputVo();
12          param.setFileName("elasticsearch-6.4.2");
13          param.setOffset(0);
14          param.setLength(1000000 * 25);
15          param.setPartNumber(1);
16          param.setSuffix(".zip");
17          param.setBytes(bytes);
18          uploadService.uploadBlock(param);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

(2)接着我们来看通过new对象的形式,不把管理权交给spring。

当我们把第10行注释的代码放开后,程序运行到第10行,这时我们在第4行注入UploadService,在第18行调用它的方法,注入调用方式就会失效,spring框架就不会替我们去管理它,这时候它这儿用到的就是通过第10行的new实例方法去对UploadService中的方法做了调用,而此时uploadBlock()这个方法中的ReadFilePathProperties这个东西并非被spring框架管理,所以就没有被自动地初始化导致报了空指针的错误(注意:如果你这时候通过new方法去调用的方法里面没有需要被初始化的对象属性(下面代码中有解释),则程序依旧正常运行,否则报空指针)。

public class TestController {
1    @Autowired
2    private FileToByteArrayService fileToByteArrayService;
3    @Autowired
4    private UploadService uploadService;
5    @Test
6    public void testDemo() throws IOException {
7        //原文件的位置(需根据自己情况修改)
8        String fileSrc = "D:\\tempfile\\elasticsearch-6.4.2.zip";
9        byte[] bytes = fileToByteArrayService.fileToBytes(fileSrc);
        /**
         * 演示过程中,下面这行代码是否注释掉说明:
         * 1.演示通过springboot注入方式去调用UploadService()中的方法需要注释掉。
         * 2.演示通过new实例方式进入到UploadService去调用方法出现空指针问题,则需要保留这行代码。
         * 3.演示通过new实例方式进入到UploadService去调用方法,通过在UploadService中set值解决问题,则这行代码不能注释掉。
         */
10        UploadService uploadService = new UploadService();
        try {
11          UploadBlockInputVo param = new UploadBlockInputVo();
12          param.setFileName("elasticsearch-6.4.2");
13          param.setOffset(0);
14          param.setLength(1000000 * 25);
15          param.setPartNumber(1);
16          param.setSuffix(".zip");
17          param.setBytes(bytes);
18          uploadService.uploadBlock(param);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
划重点:
在第18行调用uploadBlock方法时,在uploadService的uploadBlock方法中我们用下面第一行代码,
注释掉第二行,不使用ReadFilePathProperties对象中的方法,这个时候程序也会正常运行。

  String uploadPartPath = "D:\\myfile\\elasticsearch-6.4.2Zip";
//        String uploadPartPath = readFilePathProperties.getPropertisInfo();

(3)最后,我们说一下如果不把管理权交给框架,我们还是想通过new实例去调用实例中的方法,我们应该怎么办。

第一种办法,就是让实例中的调用的方法中不存在使用另一个对象的情况,其实这个问题,上面第2个解释中已经给出了一个答案。第二种办法,就是在uploadBlock方法中给ReadFilePathProperties对象set值,我们自己给他做初始化。通过这两种方式处理过后,即使不由框架为我们管理,也可以达到我们的目的,避免出现空指针的问题。

/**
 * set值部分的主要代码就是下面这一点,完整版的请自己从从git上面clone下来看吧
 */
public class UploadService {
    @Autowired
    private ReadFilePathProperties readFilePathProperties;

    public void setReadFilePathProperties(ReadFilePathProperties readFilePathProperties) {
        this.readFilePathProperties = readFilePathProperties;
    }
  
    public void uploadBlock(UploadBlockInputVo uploadBlockInputVo) {
        //code...
        ReadFilePathProperties readFilePathProperties = new ReadFilePathProperties();
        setReadFilePathProperties(readFilePathProperties);
        String uploadPartPath = readFilePathProperties.getPropertisInfo();
       //code...
         
    }
}

完整的项目地址:https://github.com/Myuhua/springboot.git

看的时候从com.jd.test.TestController这儿开始看,用小甲壳虫跑一下,针对这几种情况的演示我在代码中注明了,还有就是相关的一些文件地址,大家根据自己的情况修改一下,有原文件的地址及文件的存储地址。

 

 

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
### 回答1: 在Spring Boot中,使用多线程处理任务时,有时会遇到无法使用@Autowired注入Bean的问题。这是因为多线程环境下,不同的线程可能无法直接访问容器中的Bean。 要解决这个问题,可以使用以下方法: 1. 通过ConfigurableApplicationContext获取Bean 可以通过ConfigurableApplicationContext对象的getBean方法来手动获取Bean,而不使用@Autowired注解。代码示例: ```java @Autowired private ConfigurableApplicationContext context; // 在多线程任务中获取Bean MyBean myBean = (MyBean) context.getBean("myBean"); ``` 2. 使用@Bean和@Scope注解 可以在Bean的定义上,使用@Bean和@Scope注解指定作用域为"prototype",以确保每个线程都可以获取到一个全新的Bean实例。代码示例: ```java @Configuration public class MyConfig { @Bean @Scope("prototype") public MyBean myBean() { return new MyBean(); } } ``` 然后在需要使用多线程处理任务的中,使用注解@Autowired获取Bean。代码示例: ```java @Component public class MyTask { @Autowired private MyBean myBean; // 多线程任务代码 } ``` 通过以上两种方法,可以在Spring Boot中实现多线程处理任务,并成功注入Bean。 ### 回答2: 在Spring Boot中,使用多线程处理任务时,有时会遇到无法注入@Autowired Bean的问题。这通常是因为多线程任务是在一个独立的线程中执行的,而不是由Spring容器管理的线程。 要解决这个问题,可以尝试使用以下方法: 1. 在创建线程时手动注入Bean:在创建线程的地方,使用ApplicationContext的getBean方法手动获取需要注入的Bean,并将其传递给线程。这样就可以确保在多线程任务中使用正确的Bean实例。 2. 使用@Configurable注解:在多线程任务的上添加@Configurable注解,然后在需要注入的地方使用@Autowired注解。这样Spring将会为这个创建代理对象,并在需要注入Bean的地方自动注入相关的Bean。 3. 使用ThreadFactory和ThreadLocal:可以通过自定义ThreadFactory来创建线程,并在其中使用ThreadLocal来保存需要注入的Bean。然后,在执行任务的线程中,通过ThreadLocal获取需要的Bean实例。 需要注意的是,对于使用多线程处理任务的情况,一定要谨慎处理并发问题。确保多个线程之间不会产生数据竞争或其他并发问题,例如使用锁或其他同步机制来保护共享数据。 总而言之,处理Spring Boot中多线程任务无法注入Bean的问题可以通过手动注入Bean、使用@Configurable注解或使用ThreadFactory和ThreadLocal来解决。需要根据具体情况选择合适的方法,并注意处理并发问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小猿备忘录

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值