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

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;@Autowiredpublic 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;@Autowiredpublic MyService(MyRepository myRepository) {this.myRepository = myRepository;}
}

优点:

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

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

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

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

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

Setter方法注入

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

@Component
public class MyService {private MyRepository myRepository;@Autowiredpublic void setMyRepository(MyRepository myRepository) {this.myRepository = myRepository;}
}

优点:

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

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

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

字段注入

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

@Component
public class MyService {@Autowiredprivate MyRepository myRepository;
}

优点:

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

弊端:

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

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


http://www.mrgr.cn/news/50926.html

相关文章:

  • SAP PP常用功能之 可配置 BOM 的实现(超级BOM)
  • RISC-V笔记——RVWMO基本体
  • Vs配置opencv库 实例,opencv选用4.9.0版本,vs版本是2022社版,学习笔记不断更新
  • Servlet复习
  • 阿拉伯应用市场的特点
  • jetson nano ubuntu20.04安装ros-Noetic
  • 运行Springboot + Vue 项目
  • 【力扣 | SQL题 | 每日3题】力扣2988,569,1132,1158
  • 大健康零售电商AI知识库:优化用户体验的新引擎
  • Linux 命令 —— grep、tail、head、cat、more、less(查看日志常用命令)
  • 获取vue实例
  • 【Linux】解锁线程基本概念和线程控制,步入多线程学习的大门
  • 2024腾讯全球数字生态大会 | 线上直播活动参与教程
  • redis安装 | 远程连接
  • 利用 PyTorch Lightning 搭建一个文本分类模型
  • Web编程---配置Tomcat
  • 小米12S Ultra工程固件 资源预览 刷写说明 修复NV损坏去除主板电阻图示
  • 爬虫实战总结
  • 【ICPC】The 2021 CCPC Weihai Onsite G
  • LeetCode209.长度最小的子数组