首页 > 其他分享 >不推荐把“线程”注入到Spring、在线程中使用Spring的Bean的方法

不推荐把“线程”注入到Spring、在线程中使用Spring的Bean的方法

时间:2024-04-28 10:26:33浏览次数:27  
标签:MyService Spring myService 程中 Bean 线程 注入

一、不推荐把“线程”注入到spring

将线程注入到Spring容器中并不是一个常见的做法,而且通常也不推荐这样做,原因如下:

  1. 生命周期管理困难: Spring管理的Bean生命周期由Spring容器管理,而线程的生命周期由JVM管理。将线程注入到Spring容器中会导致线程的生命周期与Spring容器的生命周期绑定,这可能会导致线程的生命周期不受你的控制,难以达到预期的效果。

  2. 线程安全问题: Spring容器本身是线程安全的,但线程对象并不一定是线程安全的。如果将线程注入到Spring容器中,可能会引入线程安全问题,因为Spring容器对线程的管理方式与普通Bean不同。

  3. 可维护性和可读性差: 将线程注入到Spring容器中会增加代码的复杂度,降低代码的可维护性和可读性。开发人员不太容易理解和维护这样的代码。

  4. 不符合设计原则: 将线程注入到Spring容器中违反了单一职责原则和依赖倒置原则。线程应该由专门的线程管理类管理,而不应该与Spring容器耦合在一起。

因此,通常建议将需要使用Spring容器管理的Bean注入到线程中,而不是将线程注入到Spring容器中。

二、线程中使用spring的bean的方法

1、通过构造函数注入或Setter方法注入(推荐)

1.1、构造方法注入

如果你需要在线程中使用Spring的Bean,推荐通过依赖注入的方式将Bean传递到线程中。你可以通过构造函数注入或Setter方法注入,将需要的Bean传递给线程实例。这样做不仅符合Spring的依赖注入原则,还可以确保代码更易于测试和维护。

下面是一个通过依赖注入将Spring管理的Bean传递给线程的示例:

public class MyRunnable implements Runnable {
    private final MyService myService;

    public MyRunnable(MyService myService) {
        this.myService = myService;
    }

    @Override
    public void run() {
        myService.performTask();
    }
}

// 在需要创建线程的地方使用依赖注入
@Autowired
private MyService myService;

public void startThread() {
    MyRunnable myRunnable = new MyRunnable(myService);
    Thread thread = new Thread(myRunnable);
    thread.start();
}

在这个示例中,通过构造函数将MyService注入到线程中,避免了直接从ApplicationContext获取Bean的做法。这样可以保持代码的灵活性、可测试性和可维护性。

1.2、Setter方法注入

当使用Setter方法注入时,需要在线程类中定义一个Setter方法,用于接收需要注入的Bean。以下是一个使用Setter方法注入的示例:

public class MyRunnable implements Runnable {
    private MyService myService;

    // Setter方法用于注入MyService
    public void setMyService(MyService myService) {
        this.myService = myService;
    }

    @Override
    public void run() {
        if (myService != null) {
            myService.performTask();
        } else {
            throw new IllegalStateException("MyService has not been set.");
        }
    }
}

// 在需要创建线程的地方进行Setter方法注入
@Autowired
private MyService myService;

public void startThread() {
    MyRunnable myRunnable = new MyRunnable();
    myRunnable.setMyService(myService); // 使用Setter方法注入MyService
    Thread thread = new Thread(myRunnable);
    thread.start();
}

在这个示例中,MyRunnable类定义了一个setMyService方法,用于接收MyService实例。在startThread方法中,首先创建了MyRunnable实例,然后通过调用setMyService方法将MyService实例注入到线程中。这样就完成了使用Setter方法进行注入的操作。

2、Spring的getBean获取Bean,然后在线程中使用(不推荐)

可以使用Spring的ApplicationContext来获取Bean,并在线程中使用,但这种方式应该谨慎使用,并且通常不被推荐,因为它可能会带来一些潜在问题。

  1. 违背依赖注入原则: Spring推荐使用依赖注入来将Bean传递到组件中,而不是通过ApplicationContext直接获取。这种直接获取Bean的方法被称为"Service Locator"模式,这种模式会使代码耦合到Spring容器,从而降低代码的可测试性和灵活性。

  2. 不易于测试: 如果在线程中直接使用ApplicationContext获取Bean,这种代码在测试时需要模拟Spring容器,增加了测试的复杂性。

  3. 增加耦合: 线程直接获取Spring的Bean会使代码与Spring容器紧密耦合,这使得代码难以在不依赖Spring的环境中使用。

如果在某些特殊情况下确实需要在线程中获取Spring管理的Bean,请确保你在应用中正确配置了ApplicationContext,并且保证获取Bean的操作不会影响线程安全性。

标签:MyService,Spring,myService,程中,Bean,线程,注入
From: https://www.cnblogs.com/kakarotto-chen/p/18163170

相关文章

  • SpringBoot中几种好用的代码生成器(基于Mybatis-plus生成entity、mapper、xml等)
    前言熟悉Spring框架的同学一定都知道MVC开发模式吧,控制器(Controller)、业务类(Service)、持久层(Repository)、数据库映射(Mapper)、各种DO类构成了我们服务端的代码。初学的时候,觉得新鲜手写这些东西不觉得有啥,但是写久了就会觉得很烦。好不容易在数据库中写完了一遍字段,在Java代码又要......
  • 【FileZillaServer用网络驱动器作为主目录时,客户端无法列出文件】【Spring Boot安装成
    遇到的两个问题安装FileZillaServer后,把映射的网络驱动器内容作为主目录时,客户端能正常登录,但是无法列出文件。把本机的某个目录组为主目录,客户端可以正常列出文件。把SpringBoot安装成Windows服务时,访问系统中映射的网络驱动器失败(开发过程中能够正常访问,通过命令的方式......
  • Spring Boot 编写 API 的 10条最佳实践
    10个最佳实践,让您像专业人士一样编写SpringBootAPI,并结合编码示例和解释:1.RESTfulAPI设计原则:清晰一致的资源命名:使用准确反映API管理的资源的名词(例如,/products、/users)。@GetMapping("/products/{id}")publicResponseEntity<Product>getProductById(@PathVaria......
  • SpringMVC(1)-@RequestMapping的简单使用
    本文核心内容来自于韩顺平老师的课程@RequestMapping注解可以用来指定控制器或者处理器的某个方法的请求url@ControllerpublicclassUserServlet{@RequestMapping("/login")publicStringlogin(){return"login";}}1@RequestMappi......
  • SpringBoot常用注解(部分)
     @Service:注解在类上,表示这是一个业务层bean@Controller:注解在类上,表示这是一个控制层bean@Repository:注解在类上,表示这是一个数据访问层bean@Component:注解在类上,表示通用bean,value不写默认就是类名首字母小写@Autowired:按照类型(Spring容器默认单例模......
  • Spring(1)-粗解动态代理
    Spring最核心的概念是IOC、AOP,AOP的核心功能底层实现机制就是动态代理。本文使用一个案例逐步讲解动态代理的底层原理。备注:本文内容核心是韩顺平老师课程内容,这是我做的笔记外加个人理解和补充。案例需求说明我们有一个Vehicle接口,其中有一个run方法;这个接口下有两个实......
  • Spring(2)-粗解横切关注点
    本文是SpringAOP的前置内容,过渡作用。备注:本文核心内容是韩顺平老师的课程,在此基础上整理的笔记和个人理解需求有一个SmartAnimal接口,可以完成简单的加减法,要求在执行getSum()和getSub()时,输出执行前,执行过程,执行后的日志输出,请思考如何实现.日志--方法名--getSum方法......
  • Spring(3)-AOP快速入手
    经过前面Spring(1)-粗解动态代理-marigo-博客园Spring(2)-粗解横切关注点-marigo-博客园两篇内容,我们可以引入AOP了。AOP的简单理解AOP的全称(aspectorientedprogramming),面向切面编程。我们在此之前接触的更多是OOP,也就是面向对象编程。OOP和AOP有什么异同,网上有......
  • Spring(4)-AOP使用细节
    有了Spring(3)-AOP快速入手-marigo-博客园的学习,大体知道AOP的使用,接下来我们对AOP的细节进行展开。AOP-切入表达式作用:通过表达式定位一个或者多个连接点连接点可以理解成我们要切入到哪个类的哪个具体方法语法:execution([权限修饰符][返回值类型][简单类名/全类名][......
  • (一)spring beans
    1.beanDefinition首先是承载class的载体,里面包含了许多如是否单例,属性值等内容。以下只是建议代码,重在理解概念packageorg.springframework.spring.beans.factory.config;/***@ClassName:BeanDefinition//类名*@Description://描述*@Author:10300//作者......