当前位置: 首页 > article >正文

Spring-Bean的实例化和依赖注入方式

Spring-Bean的实例化和依赖注入

一、IoC(Inversion of Control) 控制反转

问题

在分层架构中,业务层要调用数据层的实现一般通过new一个对象。比如,在BlogServiceImpl中调用BlogDao的接口BlogDao blogDao = new BlogDaoImpl()。这时如果BlogDao的接口名字变了,比如变成BlogDaoImpl2。此时则需要更改业务层代码为BlogDao blogDao = new BlogDaoImpl2(),如果大型项目的话则会非常麻烦。这就是过耦合导致的问题。
而IoC就是为了解决这个问题而生的。

IoC

使用对象时,由主动new产生对象,转换为由外部(这里的外部就是IoC容器)提供,此过程中对象创建的控制权由程序转移到外部,此思想称为控制反转。IoC是一种思想,而Spring是实现这个思想的最佳实践。
依靠IoC,业务层就只需要写BlogDao blogDao;,而无需管具体的实现。

二、DI(Dependency Injection) 依赖注入

问题

当IoC容器创建好对象后,程序能正确执行吗?
仅依靠BlogDao blogDao;是不够的,虽然通过IoC已经创建好了(实例化)好了相应的对象,但对象怎么知道这个blogDao就是自己要绑定的对象呢?依赖注入就是解决这个问题的!

DI

在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入。

IoC和DI相互配合,最终目标就是为了解决:充分解耦
以上所提到的IoC容器管理的对象被称为Bean

三、IoC与Bean的实例化

IoC主要是用来管理对象,其中创建对象就是对象的实例化
其中@Bean,@Service ....都是定义Bean的方式
在Spring框架中,Bean的实例化方式主要有以下几种

1. 通过构造方法实例化

Spring默认使用无参构造方法来实例化Bean。如果Bean定义中有带参构造方法,可以通过构造器注入来实例化Bean。
无参构造器实例化:

@Component
public class MyService {
    public MyService() {
        // 无参构造方法
    }
}

带参构造器实例化:

@Component
public class MyService {
    private final MyRepository myRepository;

    @Autowired
    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository;
    }
}

2. 通过静态工厂方法实例化

可以通过指定一个静态工厂方法来实例化Bean。这种方式适用于当我们希望通过某个工厂类的静态方法创建对象时。

public class MyFactory {
    public static MyService createInstance() {
        return new MyService();
    }
}
<bean id="myService" class="com.example.MyFactory" factory-method="createInstance"/>

3. 通过实例工厂方法实例化

这种方式是通过某个工厂类的实例方法来创建Bean。我们需要先实例化工厂类,然后通过工厂类的实例方法来创建其他Bean。

public class MyFactory {
    public MyService createService() {
        return new MyService();
    }
}
<bean id="myFactory" class="com.example.MyFactory"/>
<bean id="myService" factory-bean="myFactory" factory-method="createService"/>

最常使用的是无参构造实例化的方法,在Spring框架中使用第三方的Bean时多是底层的工厂类进行实例化

四、依赖注入的方式

在Spring框架中,Bean的依赖注入有三种主要方式:

1. 构造器注入

通过构造器将依赖注入到Bean中。这种方式在对象创建时就将依赖注入,因此更加安全和不可变,适合需要强制依赖的场景。

@Component
public class MyService {
    private final MyRepository myRepository;

    @Autowired
    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository;
    }
}

优点:

  • 显式注明必须强制注入,通过强制指明依赖注入来保证这个类的运行,防止NullPointerException
    注入对象可以使用final修饰;

  • 非IOC容器环境也可使用new实例化该类的对象;

  • 避免循环依赖,如果存在循环依赖,spring项目启动的时候就会报错;
    弊端:

  • 当你有十几个甚至更多对象需要注入时,构造函数的代码臃肿,看起来不太舒服;

但是lombok插件可以完美解决,在类上声明@RequiredArgsConstructor可以完美解决

Setter方法注入

通过提供公共的Setter方法将依赖注入。这种方式适用于可选的依赖,或者需要在Bean实例化后进行配置的情况。

@Component
public class MyService {
    private MyRepository myRepository;

    @Autowired
    public void setMyRepository(MyRepository myRepository) {
        this.myRepository = myRepository;
    }
}

优点:

  • 依赖注入中使用的依赖是可选的,选择依赖的意思是注入的依赖是可以为 NULL;

  • 允许在类构造完成后重新注入;
    弊端:

  • 注入对象不能使用final修饰;

字段注入

直接通过在类的字段上使用@Autowired注解来注入依赖。这种方式简单直接,但容易导致类之间的耦合过高,通常不推荐使用。

@Component
public class MyService {
    @Autowired
    private MyRepository myRepository;
}

优点:

  • 注入方式简单,非常简洁,没有任何多余代码;

弊端:

  • 注入对象不能用final修饰;
  • 可能会导致循环依赖,启动的时候不会报错,在使用那个bean的时候才会报错;
  • 对于IOC容器以外的环境,除了使用反射来提供它需要的依赖之外,无法复用该实现类。而且将一直是个潜在的隐患,因为你不调用将一直无法发现NullPointException的存在;

所以最推荐的做法是,使用构造器进行依赖注入,在需要依赖注入的类上声明@@RequiredArgsConstructor


http://www.kler.cn/news/359534.html

相关文章:

  • Spring Boot 2.7=>3.0 升级整理
  • 【进阶OpenCV】 (12)--人脸检测识别
  • 基于SpringBoot+Vue的旅游服务平台【提供源码+答辩PPT+参考文档+项目部署】
  • 智能优化算法-生物地理学算法(BBO)(附源码)
  • 学习ROS系列 python语言
  • 起吊机革新:协议转换器解锁安全与效率
  • 提示词高级阶段学习day2.1-在提示词编写中对{}的使用教程
  • Python机器学习中的主成分分析(PCA)全面解析与应用
  • 深度学习 自动求梯度
  • kubernetes(k8s)面试之2024
  • Spring Boot:中小型医院网站开发新趋势
  • react18中如何实现同步的setState来实现所见即所得的效果
  • 【C语言】文件操作(2)(文件缓冲区和随机读取函数)
  • 当物理学奖遇上机器学习:创新融合的里程碑
  • Unity修改鼠标指针大小
  • nginx中的HTTP 负载均衡
  • 【python+Redis】hash修改
  • 真空探针台选型需知
  • Spring Boot:如何实现JAR包的直接运行
  • 首个统一生成和判别任务的条件生成模型框架BiGR:专注于增强生成和表示能力,可执行视觉生成、辨别、编辑等任务